- - PR -
C#のWindowsサービスからのProcessによるEXE起動について
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2006-08-18 16:32
どなたか教えてください。
C#のWindowsサービスから、Processを使い、アカウント、パスワード指定にてEXEを起動しようとしているのですが、「アクセスが拒否されました。」との例外が発生し、うまくいきません。ローカルのAdministratorを指定してもダメでした。 ちなみに、アカウント、パスワードなしで起動すると裏で実行されます。 以下、サンプルコードです。 // 該当プログラムを起動 Process proc = new Process(); proc.StartInfo.FileName = programInfomation.Program; proc.StartInfo.Arguments = programInfomation.Arguments; if (programInfomation.UserId != "" && programInfomation.Password != "") { proc.StartInfo.UserName = programInfomation.UserId; SecureString secStr = new SecureString(); foreach (char ch in programInfomation.Password.ToCharArray()) secStr.AppendChar(ch); proc.StartInfo.Password = secStr; if (programInfomation.Domain != "") proc.StartInfo.Domain = programInfomation.Domain; } proc.StartInfo.UseShellExecute = false; proc.StartInfo.LoadUserProfile = true; proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath); proc.StartInfo.CreateNoWindow = false; proc.Start(); 別途、セキュリティ設定なんかが必要なのでしょうか? 以上、よろしくお願いします。 | ||||
|
投稿日時: 2006-08-18 18:00
アカウント・パスワード有りでもサービスから起動する場合はこうなるのでは? | ||||
|
投稿日時: 2006-08-18 18:13
要は、Windowsの標準のタスクスケジューラーと同じようなことをしたいのです。 標準のタスクスケジューラーでは、Windowsサービスはローカルシステムで動作しており、タスクを設定する時に、動作させるアカウント、パスワードを設定します。 標準のタスクスケジューラーがうまくいくのだから、なにか方法があるものと思われます。 いかがでしょうか? | ||||
|
投稿日時: 2006-08-18 19:26
タスクスケジューラは太古より続く存在ですので .NET FrameworkのProcessとは分けて考えたほうが良いと思います。 タスクスケジューラに登録してしまうのはどうでしょう? | ||||
|
投稿日時: 2006-08-19 04:02
あるでしょうね。 少なくとも標準のタスクスケジューラが、.NET の Process クラスなんか使ってないことは間違いありません。 CreateProcessWithLogonW() API 使ってるんだと思いますよ。 | ||||
|
投稿日時: 2006-08-19 11:35
.NETのProcessでは、できないのでしょうか? .NET環境でのWindowsサービスにおいても、アクセス拒否を回避する方法があるように思うのですが... どうして、Windowsサービスと同じアカウント、パスワードで「アクセスが拒否」されるかがわかれば対処する方法も分かるように思います。 | ||||
|
投稿日時: 2006-08-19 13:57
Processだけでは出来ないでしょうね。 他にOpenDesktop APIなども関わってきていると思いますよ。これに該当するAPIが.NET Frameworkに用意されているのかは、知らないけど。 | ||||
|
投稿日時: 2006-08-31 16:14
自己解決しましたので、概要を記録させていただきます。 Windowsサービスにおいて、標準のタスクスケジューラと同様の動作を実現する方法を見つけました。 簡単に申しますと、C#のマネージコードより必要なWin32 API(アンマネージコード)を呼び出すことで 標準のタスクスケジューラと同様の動きを実現できました。 ちなみに、その流れは、次のようになります。 1.LogonUser(Win32)で、指定ユーザーでログオン(ログオントークンを取得) 2.WindowsIdentityのImpersonateで、ユーザーを偽装 3.OpenWindowStation(Win32)で、対話ウインドウステーションのハンドルの取得(winsta0) 4.GetProcessWindowStation(Win32)で、現ウインドウステーションのハンドル取得 5.SetProcessWindowStation(Win32)で、デスクトップウインドウを対話ウインドウステーションに設定 6.OpenDesktop(Win32)で、デスクトップのハンドルの取得(default) 7.該当ユーザーのログオンSIDの取得(複雑なので内容は省略) 8.対話ウインドウステーションに該当ユーザーを追加(複雑なので内容は省略) 9."default"デスクトップに該当ユーザーを追加(複雑なので内容は省略) 10.ログオンSIDのバッファの開放 11.対話ウインドウステーションとデスクトップのハンドルをクローズ(CloseWindowStation、CloseDesktop) 12.CreateProcessAsUser(Win32)で、該当プログラムを起動(lpDesktop = @"winsta0\default") 13.SetProcessWindowStation(Win32)で、ウインドウステーションの戻し 14.Undo()で、偽装ユーザーから元のユーザー権限に戻し 15.トークンや各ハンドルのクローズ(CloseHandle) なお、CreateProcessAsUserの説明に以下の内容がありましたので、Q165194を参考にさせていただ き、C#に焼き直しました。 〜〜〜〜 解説文の一部 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 ・・・ 新しいプロセスでユーザーとの対話を可能にするには、STARTUPINFO 構造体のメンバ lpDesktop に 既定の対話型ウィンドウステーションとデスクトップの名前 "winsta0\default" を指定する必要があります。 さらに、CreateProcessAsUser 関数を呼び出す前に、既定の対話型ウィンドウステーションと既定のデス クトップの両方の随意アクセス制御リスト (DACL) を変更しなければなりません。ウィンドウステーションと デスクトップの DACL で、パラメータ hToken によって表されるユーザーまたはログオンセッションへのア クセスを認めます。 ・・・ 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 Windowsサービスからのユーザーインタフェースを伴うWindowsアプリケーションの起動は推奨されない ということは、充分、理解いたしましたが、当方の都合上、今回は、上記の方法にて対応したいと思います。 |
1