Please note its very likely this is not what you want to do. Never the less I'll explain a couple of ways to do it..
Using MST files with MSIs:
You can create MST files with a user-id property and generate these for each user when they download the msi and make them install the msi with a transform:
msiexec -i c:\temp\The.msi transforms=c:\temp\YourPerso.mst
See more info here: Install a transform using the command line.
MST files used a lot in large organisations, where all the MSI's have MST files with the serial numbers and etc embedded.
To make an MST file you need to download and install Microsofts Orca Tool, its part of the Microsoft Windows SDK.
Open Orca and create an MST file out of the MSI file. Basically you open the MSI file navigate to table "Property", there you see a list of parameters.
Note in MSI file you'll see parameters which require default value.
Before you add/change parameters, create a new Transformation by clicking in menu on "Transform" -> "New Transform".
Afterwards you can change parameters or add new ones as you want to. When you have finished the parameter changes use function "Generate Transform" in "Transform" menu to generate a MST file.
If you then open the mst file with a HexEditor you can see the property you just added:
You could edit the file for each download by simply editing the value, eg:
You can of course (and probably should) do this the proper way using the API of the WindowsInstaller.Installer. Here is an example:
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
Tip: To do this with managed code you're best off using the Microsoft.Deployment.WindowsInstaller.dll
thats available as part of http://wix.codeplex.com/
Build an MSI for each user:
IMHO it would be far easier to do this with Nullsoft (WiX, InstallShield, INNO, etc) and build a MSI for each user. To do this you would embed a unique user id in for example an nsi script and kick off a MSI build for each download. During install the unique user id would be stored in a file, registry key or etc. I suggest you give this a go using this NSIS Wizard Editor to quickly whip up a basic NSI install script and build the MSI via a command line: makensis.
Note: While "Including the user-id in MSI filename" is easier than building an MSI for each user, users can easily change the filename. Its much, much less likely a user will audit the MSI using Orca to find an inbuilt user id.
The easiest and most logical way:
It's easy to send events to my server, however how do I grab the
user-id from the php server, so I can know which user did what on the .NET app?
Do what @Jhuliano Moreno and then @WouterHuysentruit recommended:
When your application starts up for the first time simply make the user login to the program using their website credentials and record their user id in a config file, registry key or database record. Basically creating a cookie so you'll know them next time the opens the program - or make them login everytime.