2015-08-23 3 views
11

У меня есть приложение .NET C#, завернутое в установщик MSI - «myprogram.exe». У меня есть сайт PHP и определенная страница, где пользователь может загрузить программу по ссылке.Как загрузить установщик MSI с аргументом для user-id

Я хотел бы отслеживать определенные события в приложении .NET. Например, «Программа открыта».

Легко отправлять события на мой сервер, однако как я могу получить идентификатор пользователя с сервера php, поэтому я могу узнать, какой пользователь сделал что-то в приложении .NET?

Я думал о передаче аргумента (идентификатора пользователя) в установщик MSI, но не смог найти способ этого.

Как мне связать идентификатор пользователя PHP и приложение .NET?

Разъяснение -

Многие люди предложили использовать систему регистрации, чтобы связать между сервером и приложением.

Это действительно самое простое решение, однако на моем веб-сайте я не заставляю пользователя входить в систему для загрузки приложения (и я не запрашиваю данные для входа в приложение .NET - его необязательно). Если нам не нужно запрашивать данные для входа, я думаю, что нам не следует, опыт для пользователя будет намного лучше (гораздо меньше шагов для использования приложения) - больше шансов для пользователя загрузить и использовать приложение Desktop.

Считает, что текущий поток -> Веб-страницу - Скачать нажмите - Выполнить - Используйте приложение (занимает 10 секунд)

С входом -> Веб-страница - Регистрация (подтверждения по электронной почте?) - Перенаправление - Скачать Клик - бег - приложение Войти - используйте приложение (занимает 60-120 секунд для пользователя)

+0

Я не совсем понял ваш вопрос. Вы хотите включить идентификатор пользователя в установщик MSI, когда пользователь загрузит его? Почему бы вам просто не внедрить систему входа, в которой вы отправляете имя пользователя и пароль на сервер, и отвечает ли пользовательским объектом/идентификатором? –

+0

Все решения, требующие от пользователя ввода информации о запуске приложения и привязки к приложению таким образом, также требуют, чтобы пользователь вводил свои данные во второй раз, что я бы хотел избежать для лучшего UX – yaron

+0

Я терплю неудачу чтобы увидеть, как логин сделает UX хуже ...Что делать, если пользователь хочет выйти или использовать одно и то же приложение, но с другим пользователем? Кроме того, знаете ли вы о безопасности? Вы навсегда будете использовать один и тот же токен/ключ? Что делать, если установка становится скомпрометированной? Будет ли пользователь повторно загружать и переустанавливать ваше приложение? –

ответ

10

Войти из программы

Лучший способ это позволить пользователю вход с теми же учетными данными в вашей программе. Таким образом, ваша программа может использовать безопасную аутентификацию OAuth2 для связи с вашим внутренним API. Это также делает его прозрачным для пользователя, что программа общается с Интернетом.

Включить пользовательский идентификатор в имени файла

Другим способом является добавление идентификатора пользователя к имени файла инсталлятора во время загрузки и извлечь его, когда программа установки запускается. Вам нужно будет проверить, позволяет ли это средство установки. Кроме того, делайте это только в том случае, если идентификатор пользователя - это UUID или что-то подобное, так как вы не хотите, чтобы пользователь угадывал другие идентификаторы.

App.config

Третий вариант заключается в добавлении идентификатор пользователя в файл App.config. Есть два способа сделать это:

  1. Создать свой .msi с App.config несжатого добавить параметр ID пользователя с фиксированным UUID.Ваш PHP-скрипт может искать UUID и заменять его в двоичном формате .msi перед его отправкой пользователю. См. Фрагмент кода под Преобразование MST
  2. Постройте .msi по запросу с пользовательским номером App.config. Это будет работать, только если ваш веб-сервер работает в Windows или у вас есть удаленный сервер сборки Windows, который может выполнять эту работу.

преобразования MST

Вы можете также использовать трансформирующего MST и использовать тот же двоичный заменить трюк, как я уже объяснял в пункте 1 под App.config.

Для обоих вариантов, вы можете использовать PHP скрипт, который использует бинарные безопасные функции, чтобы заменить значения в программе установки и посылает файл пользователю в качестве загрузки:

<?php 
$userId = // TODO get userId from the session or database 
$data = file_get_contents("./my-installer.msi"); 
// I would use UUID's for template and userId, this way the size of the installer remains the same after replace 
$data = str_replace("{fe06bd4e-4bed-4954-be14-42fb79a79817}", $userId, $data); 
// Return the file as download 
header("Cache-Control: public"); // needed for i.e. 
header('Content-Disposition: attachment; filename=my-installer.msi'); 
header('Content-Type: application/x-msi'); 
header("Content-Transfer-Encoding: Binary"); 
echo $data; 
?> 

Серийный номер

Последний способ, о котором я могу думать, это позволить программе запросить серийный номер при первом запуске и позволить вашему сайту генерировать уникальный серийный номер для каждого пользователя.

+0

Трансформация MST «трюк» делает магию для меня, спасибо. – yaron

+0

Хороший ответ (несмотря на то, что вы обладаете значком спортивного знака), вы заслуживаете награду. Я думаю, что этот подход применим к большой аудитории за пределами PHP или C#, и я отвечаю на вопрос: –

+1

Спасибо, мне тоже нравится ваш ответ. Не думал о преобразовании MST в первую очередь, так как вы можете использовать тот же подход с несжатым App.config для того, чего хочет достичь OP. –

4

Когда файл называется send, параметр UserID, если вы используете структуру MVC на вашем PHP, вам нужен новый контроллер который получает файл msi и переименовывает его в имя-userID.exe, а затем возвращает файл для загрузки через браузер.

+0

, когда я ответил на сообщение, не было ответов, показывая –

7

Um OK, обратите внимание, что это очень вероятно, это не что вы хотите сделать. Тем не менее, я объясню несколько способов сделать это ..

Использование MST файлов с ССИ:

Вы можете создать MST-файлы со свойством ID пользователя и генерировать их для каждого пользователя, когда они скачать MSI и заставить их установить MSI с преобразованием:

msiexec -i c:\temp\The.msi transforms=c:\temp\YourPerso.mst 

Смотреть подробнее здесь: Install a transform using the command line.

Вы видите, что файлы MST используются много в крупных организациях, где все MSI имеют файлы MST с серийными номерами и т. Д.

Чтобы сделать MST-файл, вам необходимо скачать и установить Microsofts Orca Tool, its part of the Microsoft Windows SDK.

Откройте Orca и создайте файл MST из файла MSI. В основном вы открываете файл MSI, переходите к таблице «Свойство», там вы видите список параметров. Примечание. В файле MSI вы увидите параметры, которые требуют значения по умолчанию.

Прежде чем добавлять/изменять параметры, создайте новое преобразование, нажав в меню «Трансформация» -> «Новое преобразование».

enter image description here

После этого вы можете изменить параметры или добавить новые, как вы хотите. Когда вы закончите изменение параметров, используйте функцию «Generate Transform» в меню «Transform», чтобы сгенерировать MST-файл.

enter image description here

Если затем открыть MST-файл с двоичным редактором вы можете увидеть свойство, которое вы только что добавили:

enter image description here

Вы можете отредактировать файл для каждой загрузки, просто редактируя значение , например:

enter image description here

Вы можете из Кур e (и, вероятно, должен) сделать это надлежащим образом с использованием API-интерфейса WindowsInstaller.Installer. Вот пример:

private function createTransform(mstfile, msi, config) 
    writeLog InfoLog, "Generating transform " & mstfile 

    dim vars: set vars = configvars(config) 

    dim createPropertyTable: createPropertyTable = "create table `Property` " & _ 
     "(`Property` char(72) not null, `Value` longchar localizable " & _ 
     "primary key `Property`)" 
    dim addProperty: addProperty = "insert into `Property` (`Property`, `Value`) values (?, ?)" 
    dim updateProperty: updateProperty = "update `Property` set `Value` = ? where `Property` = ?" 

    dim wi: set wi = createObject("WindowsInstaller.Installer") 
    dim base: set base = wi.openDatabase("base.msi", msiOpenDatabaseModeCreate) 
    base.openview(createPropertyTable).execute 
    dim tgt: set tgt = wi.openDatabase("tgt.msi", msiOpenDatabaseModeCreate) 
    tgt.openview(createPropertyTable).execute 
    dim props: set props = createObject("scripting.dictionary") 
    dim view: set view = msi.openView("select `Property`, `Value` from `Property`") 
    view.execute   
    dim record: set record = view.fetch 
    while not record is nothing 
     props(record.stringdata(1)) = true 
     base.openview(addProperty).execute record 
     tgt.openview(addProperty).execute record  
     set record = view.fetch 
    wend 

    set record = wi.createRecord(2) 
    dim prop 
    for each prop in properties_ 
     on error resume next 
     dim val: val = expand(vars, prop(DepPropertyValueIdx)) 
     if err then 
      writeLog ErrorLog, err.description 
      exit function 
     end if 
     on error goto 0 
     writeLog InfoLog, "Property " & prop(DepPropertyNameIdx) & "=" & val 
     if props.exists(prop(DepPropertyNameIdx)) then 
      record.stringdata(2) = prop(DepPropertyNameIdx) 
      record.stringdata(1) = val 
      tgt.openview(updateProperty).execute record 
     else 
      record.stringdata(1) = prop(DepPropertyNameIdx) 
      record.stringdata(2) = val 
      tgt.openview(addProperty).execute record 
     end if 
    next 
    if not tgt.generateTransform(base, mstfile) then 
     writeLog ErrorLog, "Failed to create transform" 
     exit function 
    end if 
    tgt.createTransformSummaryInfo msi, mstfile, 0, 0 
    createTransform = true 
end function 

Совет: Чтобы сделать это с помощью управляемого кода вы лучше с помощью Microsoft.Deployment.WindowsInstaller.dll Thats, доступной в рамках http://wix.codeplex.com/


Построить MSI для каждого пользователя :

IMHO было бы намного проще сделать это с помощью Nullsoft (WiX, InstallShield, INNO и т. Д.) и построить MSI для каждого пользователя. Для этого вы должны вставлять уникальный идентификатор пользователя, например, an nsi script и запускать сборку MSI для каждой загрузки. Во время установки уникальный идентификатор пользователя будет храниться в файле, в разделе реестра или т. Д. Я предлагаю вам проделать это с помощью этого NSIS Wizard Editor, чтобы быстро взломать базовый сценарий установки NSI и build the MSI via a command line: makensis.

Примечание: Хотя «Включение идентификатора пользователя в имя файла MSI» проще, чем создание MSI для каждого пользователя, пользователи могут легко изменить имя файла. Его гораздо менее вероятно, что пользователь проверит MSI, используя Orca, чтобы найти встроенный идентификатор пользователя.


Самый простой и логичный путь:

Это легко отправлять события на мой сервер, но как я могу захватить идентификатор пользователя от сервера PHP, так что я могу знать какой пользователь сделал то, что в приложении .NET?

Делайте то, что @WouterHuysentruit рекомендуется @Jhuliano Морено, а затем:

При запуске приложения в первый раз просто сделайте логин пользователя к программе, используя свои учетные данные веб-сайта и записать их идентификатор пользователя в конфиге файл, ключ реестра или запись базы данных. В основном создайте файл cookie, чтобы вы узнали их в следующий раз, когда откроете программу, или сделайте их входе в систему каждый раз.