2013-04-15 30 views
8

Windows 7(x64)およびWindows 8(x64)のC++でTeamViewerのようなリモートデスクトップアプリケーションを作成しています。私を作っ何デフォルトのデスクトップとWinlogonデスクトップの間でプロセスを切り替える方法は?

1.私はSendInput()を使って、マウス入力とキーボード入力を実装している

を立ち往生。プロセスがwinsta0\desktopで実行されたときにSendInput()が完全に機能していました。しかし、ユーザーがコンピュータをロックしたり、スクリーンセーバーが起動した後、動作しませんでした。

winsta0\winlogonで処理を実行すると、winsta0\defaultの下でSendInput()は機能しません。 「要求されたリソースが使用中です」と私はstucked:私はwinsta0\desktopからwinsta0\winlogonにプロセスを切り替えるためにSetThreadDesktop()を使用して試してみました

を試してみましたが、私はエラー170を得たもの

2。私は

を知りたい

3.私はTeamViewerのは、Winlogonプロセス、デフォルトとスクリーンセーバーの下でマウスとキーボードを制御することができますTeamViewer_Desktop.exeという名前のプロセスを持っていることに気づきました。それはどうですか?

私の質問の解決方法を理解するのに役立つコードを入力できますか?

**私のアプリケーションをデフォルトのデスクトップとWinlogonデスクトップに切り替える方法を知りたいですか?だから私はwinlogon.exeの下で実行されている別のプロセスを作成せずに、保護されたデスクトップ上でマウスとキーボードを制御することができます。

+0

あなたは、サンプルコードをしたい場合は、オープンソースのVNCプロジェクトのいずれかを使用します。ここでデモコードを要求することはあまりにも多くのことを求めています。この質問はあまりにも幅広いです。 –

+0

@DavidHeffernanありがとうございました。オープンソースのVNCプロジェクトから私の質問のためのコードを読んで見つけようとします。そして私は自分の質問を編集し、それをはっきりと作った。 – Leon

答えて

7

あなたは正しいことをしました:SetThreadDesktopが正しいです。このエラーは、現在のデスクトップ上にウィンドウなどのリソースが開いていることを示しており、切り替えができないことを示しています。テストケースを最小限に抑えようとしていた場合(ここで質問するときのように!)、それが分かっているはずです。

デスクトップを切り替えることができないチャンクが見つかるまで、プログラムの一部を切り取ります。一部のWindows APIは厄介で、デスクトップを切り替えることができないため、専用のスレッドで呼び出す必要があります。

+1

あなたは正しいです!どうもありがとう!私は最小のテストケースを試して作りました。私はコンソールプロジェクトを作成し、SetThreadDesktop()コードをテストします。できます!次のステップ私はSetThreadDesktop()がwinformプロジェクトで成功するのを妨げるものを見つけます。 – Leon

+0

@リオン、私はDelphiでこれを試しました([質問はこちら](http://stackoverflow.com/questions/41008676/how-make-setthreaddesktop-api-work-from-of-a-console-application))、成功しません:-(。いくつかの提案? – Saulo

+0

SetThreadDesktopを呼び出す前に、user32.dllから何も使用しないでください。 –

4

@NicholasWilson氏によると、SetThreadDesktop()は、デフォルトのデスクトップとwinlogonデスクトップの間でプロセスを切り替える正しい方法です。

SetThreadDesktop()の前にMessageBox()を呼び出したため、エラー170、「要求されたリソースが使用中です」が発生しました。またCreateWindow()を呼び出すと、エラーが発生する可能性があります。

SetThreadDesktop()より前に呼び出されたGUI作成に関連する関数が呼び出された場合、エラーが発生する可能性があると思います。したがって、SetThreadDesktop()を正常に呼び出す場合は、SetThreadDesktop()を呼び出す前にGUI作成関数を呼び出さないようにする必要があります。ここ

コード

コードは、指定されたデスクトップにプロセスを切り替える方法です。

用途:SetWinSta0Desktop(TEXT("winlogon"))SetWinSta0Desktop(TEXT("default"))

SetWinSta0Desktop()は機能:

BOOL SetWinSta0Desktop(TCHAR *szDesktopName) 
{ 
    BOOL bSuccess = FALSE; 

    HWINSTA hWinSta0 = OpenWindowStation(TEXT("WinSta0"), FALSE, MAXIMUM_ALLOWED); 
    if (NULL == hWinSta0) { ShowLastErrorMessage(GetLastError(), TEXT("OpenWindowStation")); } 

    bSuccess = SetProcessWindowStation(hWinSta0); 
    if (!bSuccess) { ShowLastErrorMessage(GetLastError(), TEXT("SetProcessWindowStation")); } 

    HDESK hDesk = OpenDesktop(szDesktopName, 0, FALSE, MAXIMUM_ALLOWED); 
    if (NULL == hDesk) { ShowLastErrorMessage(GetLastError(), TEXT("OpenDesktop")); } 

    bSuccess = SetThreadDesktop(hDesk); 
    if (!bSuccess) { ShowLastErrorMessage(GetLastError(), TEXT("SetThreadDesktop")); } 

    if (hDesk != NULL) { CloseDesktop(hDesk); } 
    if (hWinSta0 != NULL) { CloseWindowStation(hWinSta0); } 

    return bSuccess; 
} 

ShowLastErrorMessage()機能:

void ShowLastErrorMessage(DWORD errCode, LPTSTR errTitle) 
{ 
    LPTSTR errorText = NULL; 

    FormatMessage(
     FORMAT_MESSAGE_FROM_SYSTEM | 
     FORMAT_MESSAGE_ALLOCATE_BUFFER | 
     FORMAT_MESSAGE_IGNORE_INSERTS, 
     NULL, 
     errCode, 
     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
     (LPTSTR)&errorText, 
     0, 
     NULL); 

    if (NULL != errorText) 
    { 
     WCHAR msg[512] = {0}; 
     wsprintf(msg, TEXT("%s:\nError Code: %u\n%s\n"), errTitle, errCode, errorText); 

     LocalFree(errorText); 
     errorText = NULL; 

     OutputDebugString(msg); 
    } 
} 
関連する問題