実行ポリシーについて
概要
PowerShellスクリプトを実行したらなんか実行が無効だってエラーが出たよ!それは実行ポリシーのせい。ありがたいけど、ちょっと面倒な実行ポリシーについてです。
> .\hoge.ps1 .\hoge.ps1 : このシステムではスクリプトの実行が無効になっているため、ファイル C:\src\hoge.ps1 を読み込むことができません。詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。 発生場所 行:1 文字:1 + .\hoge.ps1 + ~~~~~~~~~~ + CategoryInfo : セキュリティ エラー: (: ) []、PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccess
実行ポリシーについて
スクリプトを実行する際の条件設定が以下の6種類存在する。デフォルトではRestricted
となっているためスクリプトを実行することができない。誤操作防止的な理由ってことかな。
- Restricted: 構成ファイルの読み込みやスクリプトの実行を行いません。既定値は "Restricted" です。
- RemoteSigned: インターネットからダウンロードされたすべてのスクリプトおよび構成ファイルが、信頼された発行元によって署名されていることを要求します。
- Unrestricted: すべての構成ファイルを読み込み、すべてのスクリプトを実行します。インターネットからダウンロードされた署名されていないスクリプトを実行する場合、スクリプトを実行する前に確認を求められます。
- Bypass: 何もブロックされず、警告もメッセージも表示されません。
https://technet.microsoft.com/ja-JP/library/dd347628.aspx
- Undefined: 現在のスコープから現在割り当てられている実行ポリシーを削除します。このパラメーターは、グループ ポリシー スコープ内で設定された実行ポリシーは削除しません。
実行ポリシーの確認
現在の実行ポリシーを確認するには以下のコマンドレットを実行する。-List
パラメータを渡すと優先順で実行ポリシーの一覧が取得できるぞ。
> Get-ExecutionPolicy Bypass > Get-ExecutionPolicy -List Scope ExecutionPolicy ----- --------------- MachinePolicy Undefined UserPolicy Undefined Process Bypass CurrentUser RemoteSigned LocalMachine Restricted
実行ポリシーのスコープはProcess
はメモリに、CurrentUser
とLocalMachine
はレジストリに格納される。また、グループポリシーでも設定することができる。
実行ポリシーの設定
実行ポリシーを変更したい場合は、管理者権限でPowerShellを起動しSet-ExecutionPolicy
コマンドレットで変更することができる。ただ、ポリシー的に実行後に設定を戻しておいたほうがいいかも。
後でだと結構忘れちゃうんで-Scope
パラメータで特定のセッションに対してのみ変更をするほうがよさげ。これなら管理者権限でなくても変更できるし: )
> Set-ExecutionPolicy -Scope Process RemoteSigned -Force
PowerShell起動時に-ExecutionPolicy
パラメータで指定してもOK。設定したポリシーは閉じるときに削除される。以下はコマンドプロンプトからスクリプトを実行する例。
CMD> PowerShell -ExecutionPolicy Bypass -file .\hello.ps1
実行ポリシーはひと手間かかるけど、間違えて.batファイルを実行して血の気が引く思いをするよりかはマシかも?
タスクスケジューラで時間のかかるタスクを待つ
tips
タスクスケジューラに登録したタスクを実行!
Start-ScheduledTask <タスク名>
そこそこ時間のかかるタスクで、終了を検知したかったので仕方なくポーリングすることに。
最初はschtasks
コマンドでバッチ書いてたけどメンドクサってなったのでPowerShellです。
■task.ps1
Start-ScheduledTask simpletask while ((Get-ScheduledTask simpletask).State -eq 'Running'){ Write-Host 'Running...' Start-Sleep 1 } Write-Host 'Complete!'
【C#】サイズと表示位置を指定してスクリーンキーボードを起動する
概要
ひょんなことからスクリーンキーボード(osk.exe)を起動するプログラムを作ることになりました。タイトルにあるとおり、キーボードのサイズと表示位置を制御したいとのこと。またWindowsAPIかよ(^ω^)
環境
Windows10
Visual Studio Community 2017
スクリーンキーボードを起動
まずはキーボードを起動してみましょう。
static void Main(string[] args) { using (Process process = new Process()) { process.StartInfo.FileName = "osk.exe"; process.Start(); } Console.ReadKey(); }
アラートが。
スクリーン キーボードを起動できません。
stackoverflowによると、Any CPUビルドだとダメっぽい。プロジェクトプロパティのビルドの設定で、32ビットを優先のチェックボックスを外すか、x64ビルドとすれば動くとのことだったのでプラットフォームターゲットをx64でビルドすることで起動することを確認しました。
サイズと表示位置を指定する
SetWindowPos
というWindowsAPIを使えば実現できそうだったのですが、引数のウィンドウハンドルがprocess.MainWindowHandle
では取れない!取得するまでにやたら時間がかかるので、タイムアウトを設けておいて取得できるまでひたすら頑張る。遅ぇぇぇ
while (0 >= (int)process.MainWindowHandle) { if (IsTimeout(startTime, timeSpan)) { Console.WriteLine("Timeout"); Environment.Exit(0); } System.Threading.Thread.Sleep(1000); Console.WriteLine("..."); process.Refresh(); }
これでサイズと表示位置を制御できると思ったら早かった。うまく動かないんです。Marshal.GetLastWin32Error()
でエラーコードを取得してエラーメッセージを見てみたらアクセス拒否!管理者権限で実行しないとダメでした。くぅー、そんなん書いてある?見つけられなかったよ。。。
苦労したけど、なんとか動いた全部入りコードがこちら。
using System; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace OnScreenKeyboard { class Program { private class User32 { internal const UInt32 WM_SYSCOMMAND = 0x112; internal const UInt32 SC_RESTORE = 0xf120; [DllImport("user32.dll", CharSet = CharSet.Auto)] internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int uFlags); internal const int SWP_NOSIZE = 0x0001; internal const int SWP_NOMOVE = 0x0002; internal const int SWP_NOZORDER = 0x0004; internal const int SWP_SHOWWINDOW = 0x0040; internal const int SWP_ASYNCWINDOWPOS = 0x4000; internal const int HWND_TOP = 0; internal const int HWND_BOTTOM = 1; internal const int HWND_TOPMOST = -1; internal const int HWND_NOTOPMOST = -2; } private class Kernel32 { [DllImport("kernel32.dll")] internal static extern uint FormatMessage(uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, StringBuilder lpBuffer, int nSize, IntPtr Arguments); internal const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; internal static string GetMessage(int errorCode) { var message = new StringBuilder(255); FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, (uint)errorCode, 0, message, message.Capacity, IntPtr.Zero ); return message.ToString(); } } static void Main(string[] args) { var onScreenKeyboad = "osk.exe"; IntPtr windowHandle = IntPtr.Zero; string processName = System.IO.Path.GetFileNameWithoutExtension(onScreenKeyboad); var query = from process in Process.GetProcesses() where process.ProcessName == processName select process; var keyboardProcess = query.FirstOrDefault(); if (keyboardProcess == null) { using (Process process = new Process()) { process.StartInfo.FileName = onScreenKeyboad; process.Start(); process.WaitForInputIdle(); var startTime = DateTime.Now; var timeSpan = new TimeSpan(0, 0, 10); while (0 >= (int)process.MainWindowHandle) { if (IsTimeout(startTime, timeSpan)) { Console.WriteLine("Timeout"); Environment.Exit(0); } System.Threading.Thread.Sleep(1000); Console.WriteLine("..."); process.Refresh(); } windowHandle = process.MainWindowHandle; var result = User32.SetWindowPos(windowHandle, 0, 0, 500, 1000, 300, User32.SWP_NOZORDER | User32.SWP_SHOWWINDOW); if (!result) { var errorCode = Marshal.GetLastWin32Error(); var message = Kernel32.GetMessage(errorCode); Console.WriteLine(message); } } } else { windowHandle = keyboardProcess.MainWindowHandle; User32.SendMessage(windowHandle, User32.WM_SYSCOMMAND, new IntPtr(User32.SC_RESTORE), new IntPtr(0)); Console.WriteLine("ReOpen"); } Console.WriteLine("Standby"); Console.ReadKey(); } static bool IsTimeout(DateTime startTime, TimeSpan timeSpan) { if (DateTime.Now - startTime > timeSpan) { return true; } return false; } } }
頭で考えるな、感じるんだ!