About Msi Installer impersonate problem.
I using vs2010 create installer project to update GPO, the problem is even I run as administrator, there still have permission issue.
The script no problem, when I just run script, it worked fine. but the custom action
when I run the import the GPO backup,
return "Name translation: Could not find the name or insufficient right to see name. "
So I think it is the Installer impersonate problem ,It not run as Administrator or not get full permission.
I search online , find a helpful script, update custom action NoImpersonate, but it run under SYSTEM, it not my need.
Custom Action In-Script Execution Options
http://msdn.microsoft.com/en-us/library/aa368069(v=vs.85).aspx
Mailbag: How to set the NoImpersonate flag for a custom action in Visual Studio 2005
http://blogs.msdn.com/b/astebner/archive/2006/10/23/mailbag-how-to-set-the-noimpersonate-flag-for-a-custom-action-in-visual-studio-2005.aspx
just change a little bit, it worked find.
if with NoImpersonate :
// NoImpersonate.js <msi-file>
// Performs a post-build fixup of an msi to change all deferred custom actions to NoImpersonate
// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyInsert = 1
var msiViewModifyUpdate = 2
var msiViewModifyAssign = 3
var msiViewModifyReplace = 4
var msiViewModifyDelete = 6
var msidbCustomActionTypeInScript = 0x00000400;
var msidbCustomActionTypeNoImpersonate = 0x00000800
var msidbCustomActionTypeTSAware = 0x00004000
if (WScript.Arguments.Length != 1)
{
WScript.StdErr.WriteLine(WScript.ScriptName + " file");
WScript.Quit(1);
}
var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
var sql
var view
var record
try
{
sql = "SELECT `Action`, `Type`, `Source`, `Target` FROM `CustomAction`";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
while (record)
{
if (record.IntegerData(2) & msidbCustomActionTypeInScript)
{
record.IntegerData(2) = record.IntegerData(2) | msidbCustomActionTypeNoImpersonate;
'change to
record.IntegerData(2) = record.IntegerData(2) & ~msidbCustomActionTypeNoImpersonate;
view.Modify(msiViewModifyReplace, record);
}
record = view.Fetch();
}
view.Close();
database.Commit();
}
catch(e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
Thursday, February 27, 2014
Thursday, February 13, 2014
How to get procress image name
My file operation monitor project need get name from process id, in case this process is create by other user, not in same session, generally , it is not, because my program run as service, it is run as local system. get process name became an issue.
it need AdjustTokenPrivileges , I use SE_DEBUG_NAME the high privilege for get process name.
Sample code :
void EnableDebugPriv()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{
wprintf(_T("ERROR %u\n"),GetLastError());
CloseHandle(hToken);
return;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!::AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL))
{
wprintf(_T("ERROR %u\n"),GetLastError());
CloseHandle(hToken);
return;
}
CloseHandle(hToken);
wprintf(_T("Should have worked"));
}
ProcessInfoStruct pInfo ;
DWORD err = ERROR_SUCCESS;
HANDLE Handle;
char buffer[MAX_PATH];
DWORD i = MAX_PATH ;
Handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processHandle);
if (Handle != 0)
{
if (QueryFullProcessImageNameA(Handle, 0, buffer, &i) != 0)
{
pProcess->processHandle = processHandle;
std::string pfullpath(buffer);
Poco::Path pathname(pfullpath);
pProcess->processName = pathname.getFileName();
pProcess->processPath = pathname.parent().toString() ;
pInfo.processHandle = processHandle ;
pInfo.processName = pProcess->processName;
pInfo.processPath = pProcess->processPath ;
processCache.add(processHandle, pInfo);
}
else
{
wprintf(_T("ERROR %u\n"),GetLastError());
}
CloseHandle(Handle);
}
else
{
wprintf(_T("ERROR %u\n"),GetLastError());
}
it need AdjustTokenPrivileges , I use SE_DEBUG_NAME the high privilege for get process name.
Sample code :
void EnableDebugPriv()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{
wprintf(_T("ERROR %u\n"),GetLastError());
CloseHandle(hToken);
return;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!::AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL))
{
wprintf(_T("ERROR %u\n"),GetLastError());
CloseHandle(hToken);
return;
}
CloseHandle(hToken);
wprintf(_T("Should have worked"));
}
ProcessInfoStruct pInfo ;
DWORD err = ERROR_SUCCESS;
HANDLE Handle;
char buffer[MAX_PATH];
DWORD i = MAX_PATH ;
Handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processHandle);
if (Handle != 0)
{
if (QueryFullProcessImageNameA(Handle, 0, buffer, &i) != 0)
{
pProcess->processHandle = processHandle;
std::string pfullpath(buffer);
Poco::Path pathname(pfullpath);
pProcess->processName = pathname.getFileName();
pProcess->processPath = pathname.parent().toString() ;
pInfo.processHandle = processHandle ;
pInfo.processName = pProcess->processName;
pInfo.processPath = pProcess->processPath ;
processCache.add(processHandle, pInfo);
}
else
{
wprintf(_T("ERROR %u\n"),GetLastError());
}
CloseHandle(Handle);
}
else
{
wprintf(_T("ERROR %u\n"),GetLastError());
}
Wednesday, February 5, 2014
MSMQ Transactional Message Processing using Multiple Receive Queues
copy from http://code-ronin.blogspot.ca/2008/09/msmq-transactional-message-processing.html
MSMQ Transactional Message Processing using Multiple Receive Queues
MSMQ Transactional Message Processing using Multiple Receive Queues
Here's the situation:
The second item can be accomplished by creating multiple receiving queues and telling them to start watching for incoming messages. The following snippets of code demonstrate how to accomplish this:
The third item can be accomplished by simply incrementing and decrementing a counter when processing begins and ends respectively; then you simply block until that counter reaches zero. You'll want to place the decrement in a finally block to ensure that the counter is decremented even if processing throws an exception. Assuming you have a Counter class that implements thread safe increment and decrement operations (see bottom), you can create a member named "ProcessingCounter", and your PeekCompleted handler has the following line to do the processing,
your Handle method would look like this,
and you could block after your MessageQueue.Close() calls like this
The following abstract class puts it all together. Simply implement the Process method and away you go!
Incidentally, the following is my implementation of a thread-safe counter.
- You want to asynchronously process messages on a queue in a transactional manner, such that the message is only taken from the queue upon successfully processing it. This allows messages that failed to be properly processed to be processed again later with a chance at success.
- You want to have multiple workers processing these messages to improve efficiency and performance of long-running processing on large numbers of messages.
- When you shutdown, you want all the processing code to complete before allowing the process to exit.
private void queue_PeekCompleted(object sender, PeekCompletedEventArgs e) { var queue = (MessageQueue)sender; var transaction = new MessageQueueTransaction(); transaction.Begin(); try { var message = queue.Receive(transaction); // process the message here transaction.Commit(); } catch (Exception ex) { // abort if processing fails transaction.Abort(); } finally { // start watching for another message queue.BeginPeek(); } }
The second item can be accomplished by creating multiple receiving queues and telling them to start watching for incoming messages. The following snippets of code demonstrate how to accomplish this:
private readonly MessageQueue[] Receivers; // member ... this.Receivers = Enumerable.Range(0, (count <= 0) ? 1 : count) .Select(i => { var queue = new MessageQueue(path, QueueAccessMode.Receive) { Formatter = new BinaryMessageFormatter() }; queue.MessageReadPropertyFilter.SetAll(); return queue; }) .ToArray(); // begin watching foreach (var queue in this.Receivers) { queue.PeekCompleted += queue_PeekCompleted; queue.BeginPeek(); } ... // closing foreach (var queue in this.Receivers) { queue.PeekCompleted -= queue_PeekCompleted; queue.Close(); // stop peeking }
The third item can be accomplished by simply incrementing and decrementing a counter when processing begins and ends respectively; then you simply block until that counter reaches zero. You'll want to place the decrement in a finally block to ensure that the counter is decremented even if processing throws an exception. Assuming you have a Counter class that implements thread safe increment and decrement operations (see bottom), you can create a member named "ProcessingCounter", and your PeekCompleted handler has the following line to do the processing,
this.Handle(queue.Receive(transaction));
your Handle method would look like this,
private void Handle(Message message) { this.ProcessingCounter.Increment(); try { // process message here; } finally { this.ProcessingCounter.Decrement(); } }
and you could block after your MessageQueue.Close() calls like this
while (this.ProcessingCounter.Value > 0) Thread.Sleep(100);
The following abstract class puts it all together. Simply implement the Process method and away you go!
public abstract class MessageProcessor<TMessage> { private readonly MessageQueue[] Receivers; private readonly Counter ProcessingCounter = new Counter(); private bool IsClosing; public MessageProcessor(string path) : this(path, 1) { } public MessageProcessor(string path, int count) : base() { if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); if (!MessageQueue.Exists(path)) MessageQueue.Create(path, true); this.Receivers = Enumerable.Range(0, (count <= 0) ? 1 : count) .Select(i => { var queue = new MessageQueue(path, QueueAccessMode.Receive) { Formatter = new BinaryMessageFormatter() }; queue.MessageReadPropertyFilter.SetAll(); return queue; }) .ToArray(); } public void Close() { this.IsClosing = true; this.OnClosing(); foreach (var queue in this.Receivers) { queue.PeekCompleted -= queue_PeekCompleted; queue.Close(); } while (this.IsProcessing) Thread.Sleep(100); this.IsClosing = this.IsOpen = false; this.OnClosed(); } public bool IsOpen { get; private set; } protected bool IsProcessing { get { return this.ProcessingCounter.Value > 0; } } protected virtual void OnClosing() { } protected virtual void OnClosed() { } protected virtual void OnOpening() { } protected virtual void OnOpened() { } public void Open() { if (this.IsOpen) throw new Exception("This processor is already open."); this.OnOpening(); foreach (var queue in this.Receivers) { queue.PeekCompleted += queue_PeekCompleted; queue.BeginPeek(); } this.IsOpen = true; this.OnOpened(); } protected abstract void Process(TMessage @object); private void Handle(Message message) { Trace.Assert(null != message); this.ProcessingCounter.Increment(); try { this.Process((TMessage)message.Body); } finally { this.ProcessingCounter.Decrement(); } } private void queue_PeekCompleted(object sender, PeekCompletedEventArgs e) { var queue = (MessageQueue)sender; var transaction = new MessageQueueTransaction(); transaction.Begin(); try { // if the queue closes after the transaction begins, // but before the call to Receive, then an exception // will be thrown and the transaction will be aborted // leaving the message to be processed next time this.Handle(queue.Receive(transaction)); transaction.Commit(); } catch (Exception ex) { transaction.Abort(); Trace.WriteLine(ex.Message); } finally { if (!this.IsClosing) queue.BeginPeek(); } } }
Incidentally, the following is my implementation of a thread-safe counter.
public class Counter { private readonly object SyncRoot = new object(); private int value; public int Value { get { lock (this.SyncRoot) { return value; } } } public int Decrement() { lock (this.SyncRoot) { return --value; } } public int Increment() { lock (this.SyncRoot) { return ++value; } } }
Subscribe to:
Posts (Atom)