WindowsRT Surface(Tablet) identifying [duplicate] - c#

This question already has answers here:
How do I get a unique identifier for a machine running Windows 8 in C#?
(4 answers)
Closed 8 years ago.
How do I uniquely identify a surface(tablet)? How do I get id of a tablet? there is a way using `HardwareIdentification.GetPackageSpecificToken(null). The problem is, it changes for simple hardware changes like disabling bluetooth. Is there a way to get unique id for a tablet which never changes?

You can use HardwareIdentification.GetPackageSpecificToken(null), see http://msdn.microsoft.com/en-us/library/windows/apps/jj553431.aspx
That function gives you a lot of information, that you can filter as you like. For example:
using System.Runtime.InteropServices.WindowsRuntime;
public static string GetMachineId()
{
var hardwareToken =
HardwareIdentification.GetPackageSpecificToken(null).Id.ToArray();
var count = hardwareToken.Length / 4;
ulong id = 0ul;
for (int i = 0; i < count; i++)
{
switch (BitConverter.ToUInt16(hardwareToken, i * 4))
{
case 1:
// processor
case 2:
// memory
case 9:
// system BIOS
id = (id << 12) ^ BitConverter.ToUInt16(hardwareToken, i * 4 + 2);
break;
}
}
return Convert.ToBase64String(BitConverter.GetBytes(id));
}
However, bear in mind that this function, and the underlying API, cannot guarantee absolute uniqueness across all the machines connected to the internet. You would typically combine this with information about the user.
Another option is to generate and store a GUID in local (non-roaming) storage, and use that as your machine id. Depending in you exact needs, this may be a better solution.
UPDATE
The Guid method is fairly simple. Just generate a new Guid the first time the app is run using
Guid installationId = Guid.NewGuid();
Then store that in a local file using
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
"installationId",
CreationCollisionOption.FailIfExists);
using (Stream fileStream = await file.OpenStreamForWriteAsync())
{
await fileStream.WriteAsync(installationId.ToByteArray(), 0, 16)
await fileStream.FlushAsync();
}
On subsequent runs, you detect that the file is there and read it.
A possible disadvantage of this method is that, when the application is uninstalled and subsequently reinstalled, a new GUID will be generated.

Related

SharpDX XAudio2: 6 SourceVoice limit

I have been playing around with SharpDX.XAudio2 for a few days now, and while things have been largely positive (the odd software quirk here and there) the following problem has me completely stuck:
I am working in C# .NET using VS2015.
I am trying to play multiple sounds simultaneously.
To do this, I have made:
- Test.cs: Contains main method
- cSoundEngine.cs: Holds XAudio2, MasteringVoice, and sound management methods.
- VoiceChannel.cs: Holds a SourceVoice, and in future any sfx/ related data.
cSoundEngine:
List<VoiceChannel> sourceVoices;
XAudio2 engine;
MasteringVoice master;
public cSoundEngine()
{
engine = new XAudio2();
master = new MasteringVoice(engine);
sourceVoices = new List<VoiceChannel>();
}
public VoiceChannel AddAndPlaySFX(string filepath, double vol, float pan)
{
/**
* Set up and start SourceVoice
*/
NativeFileStream fileStream = new NativeFileStream(filepath, NativeFileMode.Open, NativeFileAccess.Read);
SoundStream soundStream = new SoundStream(fileStream);
SourceVoice source = new SourceVoice(engine, soundStream.Format);
AudioBuffer audioBuffer = new AudioBuffer()
{
Stream = soundStream.ToDataStream(),
AudioBytes = (int)soundStream.Length,
Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
};
//Make voice wrapper
VoiceChannel voice = new VoiceChannel(source);
sourceVoices.Add(voice);
//Volume
source.SetVolume((float)vol);
//Play sound
source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
source.Start();
return voice;
}
Test.cs:
cSoundEngine engine = new cSoundEngine();
total = 6;
for (int i = 0; i < total; i++)
{
string filepath = System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.FullName + #"\Assets\Planet.wav";
VoiceChannel sfx = engine.AddAndPlaySFX(filepath, 0.1, 0);
}
Console.Read(); //Input anything to end play.
There is currently nothing worth showing in VoiceChannel.cs - it holds 'SourceVoice source' which is the one parameter sent in the constructor!
Everything is fine and well running with up to 5 sounds (total = 5). All you hear is the blissful drone of Planet.wav. Any higher than 5 however causes the console to freeze for ~5 seconds, then close (likely a c++ error which debugger can't handle). Sadly no error message for us to look at or anything.
From testing:
- Will not crash as long as you do not have more than 5 running sourcevoices.
- Changing sample rate does not seem to help.
- Setting inputChannels for master object to a different number makes no difference.
- MasteringVoice seems to say the max number of inputvoices is 64.
- Making each sfx play from a different wav file makes no difference.
- Setting the volume for sourcevoices and/or master makes no difference.
From the XAudio2 API Documentation I found this quote: 'XAudio2 removes the 6-channel limit on multichannel sounds, and supports multichannel audio on any multichannel-capable audio card. The card does not need to be hardware-accelerated.'. This is the closest I have come to finding something that mentions this problem.
I am not well experienced with programming sfx and a lot of this is very new to me, so feel free to call me an idiot where appropriate but please try and explain things in layman terms.
Please, if you have any ideas or answers they would be greatly appreciated!
-Josh
As Chuck has suggested, I have created a databank which holds the .wav data, and I just reference the single data store with each buffer. This has improved the sound limit up to 20 - however this has not fixed the problem as a whole, likely because I have not implemented this properly.
Implementation:
class SoundDataBank
{
/**
* Holds a single byte array for each sound
*/
Dictionary<eSFX, Byte[]> bank;
string curdir => Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
public SoundDataBank()
{
bank = new Dictionary<eSFX, byte[]>();
bank.Add(eSFX.planet, NativeFile.ReadAllBytes(curdir + #"\Assets\Planet.wav"));
bank.Add(eSFX.base1, NativeFile.ReadAllBytes(curdir + #"\Assets\Base.wav"));
}
public Byte[] GetSoundData(eSFX sfx)
{
byte[] output = bank[sfx];
return output;
}
}
In SoundEngine we create a SoundBank object (initialised in SoundEngine constructor):
SoundDataBank soundBank;
public VoiceChannel AddAndPlaySFXFromStore(eSFX sfx, double vol)
{
/**
* sourcevoice will be automatically added to MasteringVoice and engine in the constructor.
*/
byte[] buffer = soundBank.GetSoundData(sfx);
MemoryStream memoryStream = new MemoryStream(buffer);
SoundStream soundStream = new SoundStream(memoryStream);
SourceVoice source = new SourceVoice(engine, soundStream.Format);
AudioBuffer audioBuffer = new AudioBuffer()
{
Stream = soundStream.ToDataStream(),
AudioBytes = (int)soundStream.Length,
Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
};
//Make voice wrapper
VoiceChannel voice = new VoiceChannel(source, engine, MakeOutputMatrix());
//Volume
source.SetVolume((float)vol);
//Play sound
source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
source.Start();
sourceVoices.Add(voice);
return voice;
}
Following this implementation now lets me play up to 20 sound effects - but NOT because we are playing from the soundbank. Infact, even running the old method for sound effects now gets up to 20 sfx instances.
This has improved up to 20 because we have done NativeFile.ReadAllBytes(curdir + #"\Assets\Base.wav") in the constructor for the SoundBank.
I suspect NativeFile is holding a store of loaded file data, so you regardless of whether you run the original SoundEngine.AddAndPlaySFX() or SoundEngine.AddAndPlaySFXFromStore(), they are both running from memory?
Either way, this has quadrupled the limit from before, so this has been incredibly useful - but requires further work.

Cosmos custom OS, addmapping?

I am new to C# and is currently using COSMOS to make a simple FileSystem for my OS class. Currently I'm trying to implement a "reformat" function that, when the word "reformat" is typed into the console, the OS (emulated via QEMU), partitions the disk. Currently this is my code:
public static void console()
{
while (true)
{
Console.WriteLine("Console: ");
String input = Console.ReadLine();
if (input == "exit")
{
Cosmos.Sys.Deboot.ShutDown();
}
else if (input == "cpumem")
{
Console.WriteLine(Cosmos.Kernel.CPU.AmountOfMemory.ToString());
}
else if (input == "restart")
{
Cosmos.Sys.Deboot.Reboot();
}
else if (input == "devices")
{
var devices = Cosmos.Sys.FileSystem.Disk.Devices.ToArray();
}
else if (input == "reformat")
{
try
{
Partition part = null;
for (int j = 0; j < Cosmos.Hardware.BlockDevice.Devices.Count; j++)
{
if (Cosmos.Hardware.BlockDevice.Devices[j] is Partition)
{
part = (Partition)Cosmos.Hardware.BlockDevice.Devices[j];
}
}
var fs = new Cosmos.Sys.FileSystem.FAT32.FAT32(part);
uint cluster = 100;
fs.Format("newCluster", cluster);
}
catch
{
//Do Something warn user.
}
}
}
}
Most important is this bit:
else if (input == "reformat")
{
try
{
Partition part = null;
for (int j = 0; j < Cosmos.Hardware.BlockDevice.Devices.Count; j++)
{
if (Cosmos.Hardware.BlockDevice.Devices[j] is Partition)
{
part = (Partition)Cosmos.Hardware.BlockDevice.Devices[j];
}
}
var fs = new Cosmos.Sys.FileSystem.FAT32.FAT32(part);
uint cluster = 100;
fs.Format("newCluster", cluster);
}
catch
{
//Do Something warn user.
}
}
Which is analogous to what is located here: http://cosmos-tutorials.webs.com/atafat.html
However, when I run it, I get this error:
I believe this is because I lack this line:
Cosmos.System.Filesystem.FileSystem.AddMapping("C", FATFS);
FATFileList = FATFS.GetRoot();
Located in the link above. Is there any other way to map? Or am I missing something completely? The COSMOS documentation doesn't really tell much, the source code is honestly confusing for a beginner like me as it has no comments whatsoever on how the functions work or what they do. I am using an older version of COSMOS (Milestone 4) as it's the only one that works for Visual Studio C# 2008. Newer versions run only in Visual Studio C# 2010.
Ah, I recognize this... had to debug a similar situation on a Cosmos project I'm working on myself (I'm using the VS2010-compatible Cosmos but the same situation might apply to older versions as well...)
This can happen if you try to call a method on a null object. Type 0x........, Method 0x........ is specifically mentioning the location in the compiled code where the call failed. "Not FOUND!" means that the method it is looking for cannot be found, presumably because you called it on a null reference.
I'm testing with VirtualBox myself, and found that if you're using a brand-new blank hard disk image, there will be no Partitions on it. Thus, the condition will never get satisfied, your Partition will never get set and then Cosmos will try to execute a method on the null Partition!
Look closely at how you set the Partition (it's initialized to null). For starters I would print a simple message each time the "if (block device is partition)" condition is satisfied... I would be willing to bet it will never print.
Hope this helps... I am still learning about Cosmos and custom kernels myself but fixing the null reference in my case solved my occurrence of the problem. If that's the problem, then the next step, of course, is figuring out why you're not getting any Partitions in the first place...
The rest of your code looks fine but I am not sure how you implemented the rest of your classes. Kernel debugging can be a nightmare, good luck to you!

How to set a PreSharedKey in a RasEntry on Windows CE / Compact Framework?

Since I really don't get any progress in the last hours I need to consult you for a problem which I don't get solved.
We have a Win CE 5.0 application, written C#/Compact Frmaework 2.0 that uses RASDial to Dial into a VPN. Currently it uses PPTP but I have to change it to L2TP with a Pre Shard Key. But to be honest I have no experience in C++ and I really understand only half of the code or to be more clear I don't understand the RAS Api and Documentation in the MSDN.
I understand how to create this L2PT RAS Entry and how to Dial it but in no way I understand where and how to set the Pre Shared Key!
I found a peace of code that seems to do the same things our code does in priciple but on the Website/Board I found it the Author says this is with pre shared key but to be honest, I don't get where the key is.
(...)
// Device configuration for L2TP VPN
if (bIsL2TP) {
DWORD cbKey = 0;
if (g_sharedKey) {
cbKey = (wcslen(g_sharedKey))*sizeof(WCHAR);
}
pL2TPConfigData = (PL2TP_CONFIG_DATA)new BYTE
[sizeof(L2TP_CONFIG_DATA)+ cbKey];
ZeroMemory(pL2TPConfigData, sizeof(L2TP_CONFIG_DATA)+ cbKey);
pL2TPConfigData->dwVersion = 1;
pL2TPConfigData->dwAuthType = L2TP_IPSEC_AUTH_PRESHAREDKEY;
pL2TPConfigData->dwFlags = 0;
pL2TPConfigData->cbKey = cbKey;
pL2TPConfigData->dwOffsetKey = sizeof(L2TP_CONFIG_DATA);
pL2TPConfigData->cMyCerts = 0;
pL2TPConfigData->cRootCerts = 0;
pL2TPConfigData->dwOffsetCertHashes = sizeof(L2TP_CONFIG_DATA);
if (g_sharedKey) {
memcpy((PBYTE)pL2TPConfigData+pL2TPConfigData->dwOffsetKey,
g_sharedKey, cbKey);
}
pConfigData = (PBYTE)pL2TPConfigData;
cbConfigData = sizeof(L2TP_CONFIG_DATA) + cbKey;
}
(...)
// Create a new phone-book entry.
res = ::RasSetEntryProperties(NULL, g_entryName, &rasEntry, sizeof
(rasEntry), pConfigData, cbConfigData);
if (res != 0) {
wprintf(L"Cannot create or update the phone book entry (error# %u).
Aborting.", res);
goto exit;
}
In the code the Length (cbKey) of the key is determined but can someone explain to me where the actual key is in the code? Or can someone provide me an explaination on how to set a Pre Shared Key in RASEntry for L2TP?
Thank you so much
twickl
The pre-shared key is copied into the L2TP_CONFIG_DATA structure with this line:
memcpy((PBYTE)pL2TPConfigData+pL2TPConfigData->dwOffsetKey, g_sharedKey, cbKey);
Basically this line says "copy the data from g_sharedKey into the pL2TPConfigData instance, starting at an offset of pL2TPConfigData->dwOffsetKey for a length of cbKey"
The code wraps this in an if block, so if g_sharedKey is NULL, it doesn't do this copy.

How to determine if windows restarted?

I want my WPF application run just one time. I have no problem with this.
My problem is how can I determine if windows currently restarted?
You could write a file to disk, and then immediately mark it as 'delete on reboot' using MoveFileEx:
MSDN: http://msdn.microsoft.com/en-us/library/aa365240(v=VS.85).aspx
Pinvoke.net: http://www.pinvoke.net/default.aspx/kernel32.movefileex)
So in psuedocode:
if(File.Exists(CheckFileName))
return false; // already ran once
else {
// write out the check file
using(checkFile = File.Create(CheckFileName, ...)) {
// and mark it as delete on boot
MoveFileEx(checkFile.SafeHandle,
null,
MOVEFILE_DELAY_UNTIL_REBOOT);
return true; // ok to run
}
}
You could check and store the system uptime along with the last runtime and compare that with the current uptime.
Retrieve system uptime using C#
Some psudeocode:
DateTime computerLastStarted = Now - Uptime;
if (computerLastStarted > storedComputerLastStarted + or - tollerance) {
storedComputerLastStarted = computerLastStarted;
StartProgram();
}

Modify Emdeded String in C# compiled exe

I have an issue where I need to be able to have a compiled exe ( .net 3.5 c# ) that I will make copies of to distribute that will need to change a key for example before the exe is sent out.
I cannot compile each time a new exe is needed. This is a thin client that will be used as part of a registration process.
Is it possible to add a entry to a resource file with a blank value then when a request comes in have another application grab the blank default thin client, copy it, populate the blank value with the data needed.
If yes how? If no do you have any ideas? I have been scratching my head for a few days now and the limitation as due to the boundaries I am required to work in.
The other idea I has was to inject the value into a method, which I have no idea how I would even attempt that.
Thanks.
Convert the assembly to IL, do a textual search and replace, recompile the IL to an assembly again. Use the standard tools from the .NET SDK.
Instead of embedding the key in the assembly, put it in the app.config file (or another file delivered with the application) and prevent your application from running if the key is not present and valid. To protect it against modification by users, also add an RSA signature the config file.
This code could be used to generate XML containing your key.
public static void Main()
{
Console.WriteLine(GenerateKey());
}
public static Byte[] Transform(Byte[] bytes, ICryptoTransform xform)
{
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
using (CryptoStream cstream = new CryptoStream(stream, xform, CryptoStreamMode.Write))
{
cstream.Write(bytes, 0, bytes.Length);
cstream.Close();
stream.Close();
return stream.ToArray();
}
}
}
public static string GenerateKey()
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
// This is the private key and should never be shared.
// Generate your own with RSA.Create().ToXmlString(true).
String rsaPrivateKey = "<RSAKeyValue><Modulus>uPCow37yEzlKQXgbqO9E3enSOXY1MCQB4TMbOZyk9eXmc7kuiCMhJRbrwild0LGO8KE3zci9ETBWVVSJEqUqwtZyfUjvWOLHrf5EmzribtSU2e2hlsNoB2Mu11M0SaGd3qZfYcs2gnEnljfvkDAbCyJhUlxmHeI+35w/nqSCjCk=</Modulus><Exponent>AQAB</Exponent><P>4SMSdNcOP0qAIoT2qzODgyl5yu9RubpIU3sSqky+85ZqJHXLUDjlgqAZvT71ROexJ4tMfMOgSWezHQwKWpz3sw==</P><Q>0krr7cmorhWgwCDG8jmzLMo2jafAy6tQout+1hU0bBKAQaPTGGogPB3hTnFIr84kHcRalCksI6jk4Xx/hiw+sw==</Q><DP>DtR9mb60zIx+xkdV7E8XYaNwx2JeUsqniwA3aYpmpasJ0N8FhoJI9ALRzzp/c4uDiuRNJIbKXyt6i/ZIFFH0qw==</DP><DQ>mGCxlBwLnhkN4ind/qbQriPYY8yqZuo8A9Ggln/G/IhrZyTOUWKU+Pqtx6lOghVdFjSxbapn0W8QalNMFGz7AQ==</DQ><InverseQ>WDYfqefukDvMhPHqS8EBFJFpls/pB1gKsEmTwbJu9fBxN4fZfUFPuTnCIJsrEsnyRfeNTAUFYl3hhlRYZo5GiQ==</InverseQ><D>qB8WvAmWFMW67EM8mdlReI7L7jK4bVf+YXOtJzVwfJ2PXtoUI+wTgH0Su0IRp9sR/0v/x9HZlluj0BR2O33snQCxYI8LIo5NoWhfhkVSv0QFQiDcG5Wnbizz7w2U6pcxEC2xfcoKG4yxFkAmHCIkgs/B9T86PUPSW4ZTXcwDmqU=</D></RSAKeyValue>";
rsa.FromXmlString(rsaPrivateKey);
String signedData = "<SignedData><Key>Insert your key here</Key></SignedData>";
Byte[] licenseData = System.Text.Encoding.UTF8.GetBytes(signedData);
Byte[] sigBytes = rsa.SignData(licenseData, new SHA1CryptoServiceProvider());
String sigText = System.Text.Encoding.UTF8.GetString(Transform(sigBytes, new ToBase64Transform()));
System.Text.StringBuilder sb = new StringBuilder();
using (System.Xml.XmlWriter xw = System.Xml.XmlTextWriter.Create(sb))
{
xw.WriteStartElement("License");
xw.WriteRaw(signedData);
xw.WriteElementString("Signature", sigText);
xw.WriteEndElement();
}
return sb.ToString();
}
Example output from this code:
<?xml version="1.0" encoding="utf-16"?>
<License>
<SignedData>
<Key>Insert your key here</Key>
</SignedData>
<Signature>cgpmyqaDlHFetCZbm/zo14NEcBFZWaQpyHXViuDa3d99AQ5Dw5Ya8C9WCHbTiGfRvaP4nVGyI+ezAAKj287dhHi7l5fQAggUmh9xTfDZ0slRtvYD/wISCcHfYkEhofXUFQKFNItkM9PnOTExZvo75pYPORkvKBF2UpOIIFvEIU=</Signature>
</License>
Then you can use code like this to verify it. You never have to distribute the private key:
public static Boolean CheckLicenseSignature(String licXml)
{
try
{
System.Xml.XmlDocument xd = new System.Xml.XmlDocument();
xd.LoadXml(licXml);
String licSig = xd.SelectSingleNode("/License/Signature").InnerText;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
String rsaPublicKey = "<RSAKeyValue><Modulus>uPCow37yEzlKQXgbqO9E3enSOXY1MCQB4TMbOZyk9eXmc7kuiCMhJRbrwild0LGO8KE3zci9ETBWVVSJEqUqwtZyfUjvWOLHrf5EmzribtSU2e2hlsNoB2Mu11M0SaGd3qZfYcs2gnEnljfvkDAbCyJhUlxmHeI+35w/nqSCjCk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
rsa.FromXmlString(rsaPublicKey);
Byte[] licenseData = System.Text.Encoding.UTF8.GetBytes(xd.SelectSingleNode("/License/SignedData").OuterXml);
return rsa.VerifyData(licenseData, new SHA1CryptoServiceProvider(), Transform(System.Text.Encoding.UTF8.GetBytes(licSig), new FromBase64Transform()));
}
catch (System.Xml.XmlException ex)
{
return false;
}
catch (InvalidOperationException ex)
{
return false;
}
}
From within the capability of the .NET code itself, I'm not sure if this is doable. But it is possible to dynamically generate a .NET DLL which contains some key that can be referred from the main application. That is, if you wouldn't mind a second file in the distribution.
Or if you don't mind to use Ildasm to disassemble the .exe, change the key, then use Ilasm to reassemble, then you can do something to automate that.
The accepted answer is GARBAGE!
I HAVE DONE THIS SUCCESSFULLY. MUCH EASIER
Just put your base application (.net) that needs the key somewhere with a string resource FILLED WITH "XXXXXXXXXXXXXXX" (more than you'll need)
.Net resources are usually kept at the top of the code so you will find them fast skipping the first 100,000 bytes in my case.
Then you just read it in and look for those XXXXXX's. When you find them you replace them with the real API key and replace the rest of the X's with spaces you just trim off in code. This is the answer. It works and it works well.
ApiToken at = new ApiToken(UserId, SelectedCID);
at.MakeToken();
byte[] app = System.IO.File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.GetData("DataDirectory").ToString(), "notkeyedapp.exe"));
for (int i = 100000; i < app.Length; i++)
{
if (app[i] == 0x58 && app[i + 1] == 0x58 && app[i + 2] == 0x58)
{
for (int j = 0; j < 128; j++)
{
if (at.Token.Length >= j + 1)
app[i + j] = System.Text.Encoding.ASCII.GetBytes(at.Token[j].ToString())[0];
else
app[i + j] = 0x20;
}
break;
}
}
string filename = "SoftwareProduct for - " + BaseModel.CompanyName.Replace(".", "") + ".exe";
return File(app, System.Net.Mime.MediaTypeNames.Application.Octet, filename);
I don't think You can get away without recompiling Your .exe and having key embedded into said .exe. The compilation process can be automated though via use of ildasm.exe and ilasm.exe as Daniel Earwicker suggested in his response https://stackoverflow.com/a/2742902/2358659
I'd like to expand on that if anyone else stumbles across this topic in the future.
I recently was facing similar problem due to my poor source code version control habits. In a nutshell I had an executable that was supposed to write some data to a Google Spreadsheet by referencing it's ID. Long after executable was released came another request from a different team to use the tool, but it had to write same information into a different spreadsheet in order to keep data separate for two teams. At the time I did not have the original source code, hence I was not able to change the static variable holding the original spreadsheet ID. What I did was as follows:
Using CMD.exe → call "C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\ildasm.exe" "myApplication.exe" /out="myApplication.il"
Using Notepad++ → Find and replace original ID to new ID inside myApplication.il file. This action can also be automated by writing own C# application to do this, or using PowerShell, or using vb/j-script or using some other find and replace tool available off-the-shelf, like FART (using CMD.exe → call fart.exe myApplication.il "OldKey" "NewKey")
Using CMD.exe → call "C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe" "myApplication.il" /res="myApplication.res" /key="myApplicationKeyFile.snk"
As You see, all of these steps can be put into one .bat file that takes "NewKey" as an input and produces new .exe with NewKey embedded.
I hope that helps.
What comes to my mind, but not tried yet: Create a default String in your program, for example as
static public string regGuid = "yourguidhere";
Then, search the compiled EXE with any decent hex editor. If you find the string, replace it with another test. If you still can execute the program, you could try to automate this process and voila! Here you are.

Categories

Resources