🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

サービス

サービスとはバックグラウンド上に常駐し、長時間稼動し続ける実行可能ファイルを指します。

Q&A

1回答

4975閲覧

Windowsサービスからユーザ指定でデスクトップアプリを起動したい

pheasant99

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

サービス

サービスとはバックグラウンド上に常駐し、長時間稼動し続ける実行可能ファイルを指します。

0グッド

0クリップ

投稿2021/02/08 03:24

Windowsサービスからユーザを指定して
デスクトップを持つアプリを起動し、アプリの中からデスクトップにアクセスしたいのですが
起動するアプリ側で次のような2つの現象が出て困っています。
アプリを単独で起動すると問題なく動作します。
また、サービスからは指定ユーザで起動される事は確認できています。
(PowerShellでプロセス一覧で確認済み)
ちなみに起動のトリガーはホットフォルダーなのでタイミングは問題ないと思います。

【現象1】
log4netのログが出力されない。
C#のプログラムからテキスト出力は出来ます。
【現象2】
アプリ内でデスクトップにアクセス(画像を取得)が出来ない。
単体では問題ないのでサービス側の起動方法に何か考慮不足があるのかと
思っていますが、試行錯誤してもなかなか分かりません。

プロセス起動のソースは長いので取りあえず使っているAPIをピックアップしました。
ご存じの方がいらっしゃいましたらご教示頂けると幸いです。

――― プロセス起動で使っているAPI
//起動するユーザで認証
Win32Api.logonUser()
//偽装特権の有効化
Win32Api.OpenProcess()
Win32Api.OpenProcessToken()
Win32Api.LookupPrivilegeValue()
Win32Api.AdjustTokenPrivileges(
//新しいWindowStationを設定
Win32Api.GetProcessWindowStation()
Win32Api.openWindowStation()
//デスクトップのオープン
Win32Api.OpenDesktop()
Win32Api.SetProcessWindowStation()、
Win32Api.LoadUserProfile()
//ユーザの偽装を実施
Win32Api.ImpersonateLoggedOnUser()
//リダイレクトの設定
Win32Api.CreatePipe()
Win32Api.CreateEnvironmentBlock()
//環境ブロック
Win32Api.CreateEnvironmentBlock()
Win32Api.DestroyEnvironmentBlock()
//プロセス起動
Win32Api.CreateProcessAsUser()
Win32Api.OpenProcess()
//プロセスの優先度
Win32Api.OpenProcess()
Win32Api.SetPriorityClass()
// 偽装の解除
Win32Api.RevertToSelf()
―――

・起動するアプリ側のソース

C#

1namespace RPEtpCon 2{ 3 class Program 4 { 5 //ロガー 6 public static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 7 8 static void Main(string[] args) 9 { 10 logger.Info("コンソールアプリ(窓無し)を起動されました"); 11 12 File.WriteAllText(@"C:\RPEtest\log\test.txt", "Good morning!\n"); 13 System.Threading.Thread.Sleep(3000); 14 15 File.AppendAllText(@"C:\RPEtest\log\test.txt", "Good morning! 3秒後\n"); 16 17 // プライマリスクリーン全体 18 Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); 19 logger.Debug("DeskTopを取得準備 "); 20 21 File.AppendAllText(@"C:\RPEtest\log\test.txt", "Good morning! DeskTopを取得準備\n"); 22 23 try 24 { 25 Graphics graphics = Graphics.FromImage(bitmap); 26 27 File.AppendAllText(@"C:\RPEtest\log\test.txt", "Good morning! Graphics.FromImage()\n"); 28 29 // 画面全体をコピーする 30 graphics.CopyFromScreen(new Point(0, 0), new Point(0, 0), bitmap.Size); 31 32 File.AppendAllText(@"C:\RPEtest\log\test.txt", "Good morning! Graphics.CopyFromScreen()\n"); 33 34 try 35 { 36 // bitmap.Save(@"C:\RPEtest\desktop.bmp"); 37 bitmap.Save(@"C:\RPEtest\desktop.jpg"); 38 39 logger.Debug("DeskTopを保存 "); 40 File.AppendAllText(@"C:\RPEtest\log\test.txt", "Good morning! DeskTopを保存\n"); 41 42 // グラフィックスの解放 43 graphics.Dispose(); 44 } 45 catch (Exception e) 46 { 47 logger.Error("DeskTopを保存err " + e.Message); 48 File.AppendAllText(@"C:\RPEtest\log\test.txt", "DeskTopを保存err " + e.Message +"\n"); 49 } 50 } 51 catch (Exception e) //ここでキャッチされる。 52 { 53 logger.Error("DeskTopを取得err " + e.Message);54 File.AppendAllText(@"C:\RPEtest\log\test.txt", "DeskTopを取得err " + e.Message + "\n"); 55 } 56 57 System.Threading.Thread.Sleep(7000); 58 logger.Info("コンソールアプリ(窓無し)を終了ました"); 59 File.AppendAllText(@"C:\RPEtest\log\test.txt", "コンソールアプリ(窓無し)を終了ました\n"); 60 } 61 } 62}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

【現象1】

log4netのログが出力されない。

とりあえずlog4netの内部デバッグをしてみてはどうでしょう。
How to track down log4net problems

【現象2】
アプリ内でデスクトップにアクセス(画像を取得)が出来ない。

Vista以降はそもそもサービスはGUIにアクセス出来ないようですが。回避策もあるようですが、するべきではないという記述も見られます。
Allow Windows service to interact with desktop より

However, note that as of Windows Vista, services are strictly forbidden from interacting directly with a user:

Important: Services cannot directly interact with a user as of Windows Vista. Therefore, the techniques mentioned in the section titled Using an Interactive Service should not be used in new code.

投稿2021/02/08 05:39

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pheasant99

2021/02/08 11:59

ありがとうございます。 log4netの内部ログを取得してみました。 どうも次の行がヒントのようですが、原因が分かりません。 元々、通常の起動では正常にログが出ているので(汗) log4net:ERROR Could not create Appender [tryLogAppender] of type [log4net.Appender.RollingFileAppender]. Reported error follows. > Vista以降はそもそもサービスはGUIにアクセス出来ないようですが。 それは知っていますが、要は「リモート デスクトップ接続」のような事を実現したいです。 そのためにユーザを指定して認証後にそのユーザで起動しています。 「リモート デスクトップ接続」のように全GUI操作を遠隔で行うのではなく 部分的な定型操作をPGから行うものを実現したいのです。 何かしら起動時の設定が足らないような気がするのですが(汗)
退会済みユーザー

退会済みユーザー

2021/02/08 13:29

リンク先に回避策の記事もあるので、追ってみてはどうでしょう。 WTSEnumerateSessions を使用するみたいですが、実際に試した訳ではないのでそれらについてはコメントを差し控えます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問