2013-01-27 1 views
10

Shell32 및 Folder.GetDetailsOf()를 사용하여 WTV 파일에서 메타 데이터를 가져 오는 .NET 4.0 라이브러리가 있습니다. 콘솔 및 Windows Forms 응용 프로그램에서 문제없이 성공적으로 사용했습니다. 그러나 .NET 4.0 Windows 서비스에서 구성 요소를 호출 할 때 Shell 클래스를 시작하기위한 호출이 COM 오류를 발생시키는 이유가 있습니다..NET Windows 서비스에서 Shell32.dll 호출

라이브러리 내부 실패 코드 :

Shell32.Shell 쉘 = 새로운 쉘();

오류 :

'Shell32.Shell'유형을 인터페이스 유형 '시스템 .__하여 ComObject을'의 COM 개체를 캐스팅 할 수 없습니다. 다음 오류로 인해 IID '{286E6F1B-7113-4355-9562-96B7E9D64C54}'인터페이스의 COM 구성 요소에서 QueryInterface 호출이 실패했기 때문에이 작업이 실패했습니다. 해당 인터페이스가 지원되지 않습니다 (HRESULT의 예외 : 0x80004002 (E_NOINTERFACE)). .

필자는 Apartment Threading, COM Interops, Dynamic, PIA 's, etc, etc, 등등에 대한 필자의 글을 읽었습니다. 그러나 발견 된 솔루션 조합은 문제를 해결하지 못했습니다. Interop을 볼 수없는 다른 스레드의 호출이어야합니다. 도와주세요, 제발 :)

답변

3

나는 이것이 기본적으로 Windows 서비스가 데스크톱과 상호 작용할 수있는 권한이 없다는 사실과 관련이 있다고 생각됩니다.

이론을 테스트하려면 데스크톱 상호 작용을 허용하도록 서비스 권한을 (적어도 임시 기준으로) 재구성하십시오. 다음 링크

https://superuser.com/questions/415204/how-do-i-allow-interactive-services-in-windows-7

UPDATE

The Shell32 functionality works just fine as LocalSystem, even when the "Allow service to interact with desktop" checkbox is unchecked, but doesn't seem to work at all under a specific user account (whether limited or admin)

Using SHFileOperation within a Windows service

당신이 일이 점점에 성공하면 것을 수행 과정을 안내, 당신이 어떤 UI 상호 작용을 억제 있는지 확인하십시오. 이 작업을 수행하는 방법에 대한 정보는이 대답에 볼 수 있습니다 :

https://stackoverflow.com/a/202519/141172

+0

사용 권한 문제에 대해 동의합니다. +1 – FrostyFire

+0

+1이지만 [MSDN] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms683502%28v=vs.85%29.aspx)에 따르면 Vista 이상 서비스는 데스크톱과 전혀 상호 작용할 수 없습니다 (직접, 어쨌든). 연결된 페이지에서 : "** 중요 ** 서비스는 Windows Vista 사용자와 직접 상호 작용할 수 없습니다.". 나는 그 경우에 "기본적으로"말할 것이라고 확신하지 못합니다. :-) –

+0

@KenWhite : Windows 8을 선택하기 만하면 상호 작용을 허용하는 확인란이 아직 있습니다. 내 생각 엔 로그인 한 사용자의 데스크톱과 상호 작용할 수 없다는 말입니다. 그러나, 나는 그 권한을 가진 서비스가 여전히 자신의 * 데스크탑 세션을 얻는다고 생각한다. –

0

나는 Windows 서비스를 생성하고 난 P/호출과 shell32를 불렀다.

[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)] 
static extern bool CreateProcessAsUser(
    IntPtr hToken, 
    string lpApplicationName, 
    string lpCommandLine, 
    ref SECURITY_ATTRIBUTES lpProcessAttributes, 
    ref SECURITY_ATTRIBUTES lpThreadAttributes, 
    bool bInheritHandles, 
    uint dwCreationFlags, 
    IntPtr lpEnvironment, 
    string lpCurrentDirectory, 
    ref STARTUPINFO lpStartupInfo, 
    out PROCESS_INFORMATION lpProcessInformation); 

과에서를 : I 사용자 (하지 시스템) 데스크톱과 상호 작용하도록 프로세스를 만들 필요가

첫째 : 내 경우

, 그것은 파일에 마우스 오른쪽 버튼으로 클릭을 시뮬레이션이었다 이 과정 나는

[DllImport("kernel32.dll")] 
private static extern IntPtr LoadLibrary(string dllName); 
[DllImport("user32.dll", CharSet = CharSet.Auto)] 
static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax); 

내 Windows 서비스이 함께 shell32를의 differents의 값을 찾아 우리와 같은 데스크톱과 상호 작용할 수 있습니다 (부하가 그 값을 추출)을 shell32를 라이브러리 사용 어 ;-)

당신은 내가 명령 줄 응용 프로그램 (콘솔)와 최근에 같은 문제가 있었이 website

14

에 P/호출에 대한 자세한 내용을 확인할 수 있습니다.프로그램의 Main() 메소드에 [STAThread] 속성으로 주석을 추가해야했습니다. 진입 점에 [MTAThread]이라는 주석이있는 경우 똑같은 방법으로 비참하게 실패합니다. 나는 그것이 도움이되기를 바랍니다.