2013-01-27 6 views
10

У меня есть библиотека .NET 4.0, которая использует Shell32 и Folder.GetDetailsOf() для получения метаданных из файлов WTV. Я успешно использовал его с консольными и Windows Forms приложениями без проблем. Но по какой-то причине при вызове компонента из .NET 4.0 службы Windows вызов инициировать класс оболочки вызывает ошибку COM.Вызов Shell32.dll из службы .NET Windows

Код, который терпит неудачу в библиотеке:

Shell32.Shell оболочки = новый Shell();

Ошибка:

Невозможно бросить COM объект типа 'System .__ ComObject' для взаимодействия типа 'Shell32.Shell'. Эта операция завершилась неудачно, потому что вызов QueryInterface для COM-компонента для интерфейса с IID '{286E6F1B-7113-4355-9562-96B7E9D64C54} завершился неудачно из-за следующей ошибки: такой интерфейс не поддерживается (исключение из HRESULT: 0x80004002 (E_NOINTERFACE)) ,

Я прочитал, что заполнял Thread Threading, COM Interops, Dynamic, PIA и т. Д. И т. Д. :). Но ни одна комбинация решений, которые я нашел, не решила проблему. Это должен быть вызов из другого потока, который не может видеть 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

Если удастся получить эту работу, убедитесь, что вы подавить любое взаимодействие пользовательского интерфейса. Информация о том, как сделать это доступно в этом ответе:

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, и я назвал Shell32 с P/Invoke.

В моем случае это было имитируя правой кнопкой мыши на файле:

Во-первых, мне нужно создать процесс, как пользователь (не системы), чтобы взаимодействовать с рабочим столом:

[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); 

И в этот процесс, я использовал Shell32 Library (нагрузка затем извлечь значение)

[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); 

My Windows Service может найти дифферент значения Shell32 с этим и взаимодействовать с рабочим столом, как и мы эр ;-)

Вы можете найти более подробную информацию для P/Invoke на этом website

14

Я была такая же проблема совсем недавно с приложением командной строки (консоли).Оказывается, требуется аннотировать метод Main() программы с атрибутом [STAThread]. Также было отмечено, что он терпит неудачу точно так же, если вместо точки входа указывается [MTAThread]. Я надеюсь, что это помогает.