tags:

views:

406

answers:

5

We are developing a WinForm application that we want to deploy to certain users machine. We would like to uniquely identify each application installed with some sort of "code" that we can define before installing on their system.

Right now we plan to put the unique code (that we type ourselves) in an xml or text file and have the application read it on install. The application would delete that file after installation and save it somewhere.

We want to be able to type that code ourselves so we can keep track, but is there a better of doing this instead of putting it in some sort of flat file and having the application delete it after install?

A: 

Personally, if I were going to write a scheme like this, I would have a server that the application would check with on first run. The server would generate an ID for the computer (probably a GUID), which the client application would then save.

Doing this manually at the time of install is probably unlikely if using a scheme like this, but there's no reason the server couldn't keep a catalog of computers with the application installed for you, if that's the only reason for doing it manually.

DannySmurf
Unfortunately, the application cannot contact any servers (I don't have the power to change this decision) and the unique ID must be defined by the person distributing the application, so it can't be a generated ID.
+1  A: 

You could use the MAC ID of the primary network card, the serial number of the system drive, or some combination thereof. If you have full control over the users' machines then the CPUID might also be suitable.

It depends on how much you trust your users. If the ID is primarily for identification, then the above will work. If it's for some sort of security system or contains additional information (e.g. which features in the app to switch on), then some kind of server-based or Active Directory-based solution (assuming an intranet environment) would probably be better.

Andrew Rollings
+1  A: 

Add a Custom Action in your MSI installer that generates a GUID on the fly and stores it in the registry. The program would then access that registry entry whenever necessary.

Otávio Décio
+1  A: 

If you use an MSI to install the application you could edit each MSI to include the special code and write it to the regsitry as part of the install.

You can use ORCA to edit MSI's manually - You can even use scripts to access the MSI and change values in it so you could write a small application to do that part of it.

Otherwise you could encrypt it into the configuration file itself and enter it on start up.

Without a little more information it is pretty tricky to help out here.

I use this script (WiRunSQL.vbs) to access MSIs

' Windows Installer utility to execute SQL statements against an installer database
' For use with Windows Scripting Host, CScript.exe or WScript.exe
' Copyright (c) 1999-2001, Microsoft Corporation
' Demonstrates the script-driven database queries and updates
'
Option Explicit

Const msiOpenDatabaseModeReadOnly = 0
Const msiOpenDatabaseModeTransact = 1

Dim argNum, argCount:argCount = Wscript.Arguments.Count
If (argCount < 2) Then
    Wscript.Echo "Windows Installer utility to execute SQL queries against an installer database." &_
     vbLf & " The 1st argument specifies the path to the MSI database, relative or full path" &_
     vbLf & " Subsequent arguments specify SQL queries to execute - must be in double quotes" &_
     vbLf & " SELECT queries will display the rows of the result list specified in the query" &_
     vbLf & " Binary data columns selected by a query will not be displayed" &_
     vblf &_
     vblf & "Copyright (C) Microsoft Corporation, 1999-2001.  All rights reserved."
    Wscript.Quit 1
End If

' Scan arguments for valid SQL keyword and to determine if any update operations
Dim openMode : openMode = msiOpenDatabaseModeReadOnly
For argNum = 1 To argCount - 1
    Dim keyword : keyword = Wscript.Arguments(argNum)
    Dim keywordLen : keywordLen = InStr(1, keyword, " ", vbTextCompare)
    If (keywordLen) Then keyword = UCase(Left(keyword, keywordLen - 1))
    If InStr(1, "UPDATE INSERT DELETE CREATE ALTER DROP", keyword, vbTextCompare) Then
     openMode = msiOpenDatabaseModeTransact
    ElseIf keyword <> "SELECT" Then
     Fail "Invalid SQL statement type: " & keyword
    End If
Next

' Connect to Windows installer object
On Error Resume Next
Dim installer : Set installer = Nothing
Set installer = Wscript.CreateObject("WindowsInstaller.Installer") : CheckError

' Open database
Dim databasePath:databasePath = Wscript.Arguments(0)
Dim database : Set database = installer.OpenDatabase(databasePath, openMode) : CheckError

' Process SQL statements
Dim query, view, record, message, rowData, columnCount, delim, column
For argNum = 1 To argCount - 1
    query = Wscript.Arguments(argNum)
    Set view = database.OpenView(query) : CheckError
    view.Execute : CheckError
    If Ucase(Left(query, 6)) = "SELECT" Then
     Do
      Set record = view.Fetch
      If record Is Nothing Then Exit Do
      columnCount = record.FieldCount
      rowData = Empty
      delim = "  "
      For column = 1 To columnCount
       If column = columnCount Then delim = vbLf
       rowData = rowData & record.StringData(column) & delim
      Next
      message = message & rowData
     Loop
    End If
Next
If openMode = msiOpenDatabaseModeTransact Then database.Commit
If Not IsEmpty(message) Then Wscript.Echo message
Wscript.Quit 0

Sub CheckError
    Dim message, errRec
    If Err = 0 Then Exit Sub
    message = Err.Source & " " & Hex(Err) & ": " & Err.Description
    If Not installer Is Nothing Then
     Set errRec = installer.LastErrorRecord
     If Not errRec Is Nothing Then message = message & vbLf & errRec.FormatText
    End If
    Fail message
End Sub

Sub Fail(message)
    Wscript.Echo message
    Wscript.Quit 2
End Sub

And I call it like this.

wscript D:\Scripts\wirunsql.vbs D:\MSI\msiName.msi "Update ISProductConfigurationProperty Set Value = 'Name of my Product' WHERE (Property = 'ProductName')"
Brody
+1  A: 

I would recommend using NSIS (Nullsoft Install System) for your setup and setting up a variable inside your installation script that is saved the registry somewhere upon installation.

Variables inside NSIS scripts can be defined at compilation using a special command line switch. This makes it possible to create a lightweight c# or vb.net application that takes in the unique ID of your choosing and builds an installation with the ID embedded.

This way it only takes one click to create a new installation for a customer. You could also wire up your .NET build application to a SQL Express database (or equivalent) and save the customer ID automatically for later.

Robert Venables