Я успешно разработал и развернул приложение ClickOnce, которое регистрирует связанное расширение файла, например *.abc
. Когда я нажимаю на названный файл x.abc
или если я ввожу x.abc
от командной строки запускается приложение ClickOnce, и я могу получить файл через специализированный API. Я могу также запустить приложение программно со следующим кодом:
System.Diagnostics.Process.Start ("x.abc");
Все хорошо работает на моем поле Windows Vista 64 битов.
Однако, если я пытаюсь сделать точно то же самое в Windows 7 (также 64 бита), у меня есть очень странная проблема. Вот то, что я наблюдаю:
x.abc
путем двойного щелчка по нему от работ Проводника.x.abc
от работ командной строки.Process.Start("x.abc")
не запускает приложение; однако, объект процесса возвратил шоу, что не было ошибки и что приложение ClickOnce, из которого так или иначе выходят сразу. Но даже a Trace
в самом начале ClickOnce никогда не достигается приложение.Process.Start("x.bat")
с файлом x.bat
содержа одну строку x.abc
не запускает приложение ClickOnce также! То же x.bat
запущенный с работ Проводника (конечно).Попытка проанализировать, что происходит с ProcMon
не было очень полезно, поскольку за процессом ClickOnce запуска приложения очень трудно следовать с моей точки зрения. Я наблюдаю rundll32
взятие за работу, но никакое доказательство любого отказа.
Программа, которая делает Process.Start
полное доверительное консольное приложение с действительно, ничто не полагает.
Я не вижу то, что изменилось относительно того, как приложения ClickOnce обрабатываются в Windows 7 и почему Process.Start
не сделал бы точно того же как запуска файла из Проводника. Стоит, чтобы упомянуть что с помощью большего количества усовершенствованных версий Start
метод с ProcessStartInfo
и установка UseShellExecute
кому: true
не помог также.
Запуск cmd
с Process.Start
и затем попытка запуститься x.abc
шоу точно та же проблема. Если я сравниваю параметры среды с a cmd
запущенный вручную, я вижу различия в как ProgramFiles
определяется (первый указывает на C:\Program Files (x86)
тогда как вторые точки к C:\Program Files
). Приложения, запущенные с моего приложения.NET, запущены на 32-разрядном уровне (SysWoW64) эмуляции.
Я смог воспроизвести отказ запуска x.abc
путем запуска 32-разрядной версии командной строки (то есть, %windir%\SysWoW64\cmd.exe
) и затем ввод x.abc
при подсказке. Я также нашел ужасное обходное решение, которое должно запустить 64-разрядную командную строку с 32-разрядной среды путем запуска %windir%\Sysnative\cmd.exe /C x.abc
вместо x.abc
.
Но я использовал бы очевидный способ выполнения его (или сделайте, чтобы представитель Microsoft сказал мне, что это - действительно проблема с Windows 7 и/или ClickOncce и что это будет скоро зафиксировано).
Похоже, вы создали свое приложение, используя x32 в качестве целевой платформы, что заставляет Process.Start
порождать x32-разрядный процесс. И, как я полагаю, Windows 7 хранит ассоциации файлов для 32-битных и 64-битных приложений отдельно.
Если у вас нет COM или неуправляемых 32-битных зависимостей, вы можете попробовать создать свое приложение для целевой платформы «Любая» вместо 'x32'.
Я исследовал дальше и обнаружил, что установщик ClickOnce создает следующую команду открытого доступа для любого связанного расширения файла (GUID уникален для каждого приложения):
rundll32.exe dfshim.dll, ShOpenVerbExtension {dce01888-35e8-4df3-af35-cd971f520d8d} %1
Используя Process Monitor , я обнаружил, что 32-разрядная версия не может открыть раздел реестра HKCU \ Software \ Classes \ Wow6432Node \ CLSID \ {dce01888-35e8-4df3-af35-cd971f520d8d}
. (64-разрядная версия успешно открывает его по адресу HKCU \ Software \ Classes \ CLSID \ {dce01888-35e8-4df3-af35-cd971f520d8d}
.)
Так что для меня это действительно ошибка ClickOnce. На вашем месте я бы использовал этот грязный % WinDir% \ system32 \ cmd.exe / C test.abc
обходной путь. (Кажется, что работает - попробовал из диспетчера задач x32.)
Я добавил эту проблему в Microsoft Connect (обновление 2013-02-13: эта ссылка гнилая).
That only might start system wide extensions like .bat
or even .txt
, but it can't always launch correct programs through extensions.
Instead try this API or a similar alternative in .NET:
FindExecutable : shell32.dll Alias : "FindExecutableA" / "FindExecutableW" return type : int parameters : · lpFile Pointer to a null-terminated string specifying a имя файла. Это может быть документ или запускаемый файл. · lpDirectory Указатель на строку с нулевым символом в конце, определяющую каталог по умолчанию. · lpResult Указатель на буфер для получения имени файла, когда функция возвращается. Это имя файла строка с завершающим нулем, определяющая исполняемый файл запускался при «открытии» ассоциация запускается в файле указанный в параметре lpFile.
Это возвращает целое число больше нуля в случае успеха, а значение char будет содержать строку с завершающим нулем , которая указывает на исполняемый файл, который запускает это расширение файла then you can use it like this
System.Diagnostics.Process.Start ("program.exe $:\path\x.abc");
Instead of program.exe
, you'll use the result of the API function, and you'll use the path to the file separated with a space just like a command line.
As for the application failure, it might indicate that the program needs administrative rights to run correctly. cmd
already got administrative rights, so it can make child applications inherit it, but not windows API. createprocess
allows you to use LPSECURITY attributes which can help in launching this program with the correct privileges.
Вы пробовали использовать ShellExecute () ; API?
[DllImport("Shell32.dll",CharSet=CharSet.Auto)]
public static extern IntPtr ShellExecute(
IntPtr hwnd,
string lpVerb,
string lpFile,
string lpParameters,
string lpDirectory,
int nShowCmd );
ShellExecute(this.Handle,"open","x.abc","","",3);
Вы также можете попробовать функцию Shell (); , которая является частью платформы