Thursday, December 11, 2014

Error RC2144 : PRIMARY LANGUAGE ID not a number

Fix for “Error RC2144 : PRIMARY LANGUAGE ID not a number”

in visual studio express 2013 , do not have Resources editor,  use the txt editor create a RC file.
include  string table for multiple language support.

Adding #include <windows.h> seems to fix it…for now.

Resources.rc


#include <windows.h>
#include "resource.h"

etc...


/////////////////////////////////////////////////////////////////////////////
// English (United States) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)

LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
STRINGTABLE DISCARDABLE
BEGIN
...
END


#endif    // English (United States) resources


#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
STRINGTABLE DISCARDABLE
BEGIN
.....
END

Friday, December 5, 2014

COM object with Single-threaded apartment threading model.

To implement the (single-threaded) apartment threading model, you must

follow a few rules:

The first thread in the application that gets created is COM's main

thread. This is typically the thread on which WinMain was called. This

must also be the last thread to uninitialize COM.
Each thread in the apartment threading model must have a message loop,

and the message queue must be checked frequently.
When a thread gets a pointer to a COM interface, that pointer may only

be used in that thread.
The single-threaded apartment model is the middle ground between

providing no threading support and full, multi-threading support of the

free threading model. A server committing to the apartment model

promises that the server has serialized access to all of its global data

(such as its object count). This is because different objects may try to

access the global data from different threads. However, the object's

instance data is safe because the methods are always called on the same

thread.
Typically, controls for use in Web browsers use the apartment threading

model because browser applications always initialize their threads as

apartment.

Friday, June 6, 2014

sync time between 2 windows servers

1:Make sure
HKLM\SYSTEM\CurrentControlSet\services\W32Time\Parameters\Type  value is NT5DS

2:Then type this at an elevated command prompt:
w32tm /config /manualpeerlist:10.0.0.1,0x8 /syncfromflags:MANUAL /update

3:Then restart the Windows Time service and type this to confirm it worked:
w32tm /query /status

Tuesday, June 3, 2014

Install /Unstall .INF driver visual studio setup project

I created a minifilter driver for log /block file access. and need install the driver use visual studio setup project.
Create custom action for install/uninstall .INF driver.

rundll32 syssetup,SetupInfObjectInstallAction DefaultInstall 128 .\xxx.inf

rundll32 setupapi,InstallHinfSection DefaultUninstall 132 " +chr(34) + installdir +"Drivers\xxx.inf" + chr(34)


Function InstallDriver()
on error resume next
Dim WshShellInstallTest, oExec ,windowsdir
Set WshShellInstallTest = CreateObject("WScript.Shell")
if (Err.Number <> 0) Then
MsgBox "WScript.Shell" & Err.Number & " " & Err.Description
Err.Clear
end if
Dim installdir
installdir = Session.Property("CustomActionData")
if (Err.Number <> 0) Then
MsgBox "CustomActionData" & Err.Number & " " & Err.Description
Err.Clear
end if
WshShellInstallTest.CurrentDirectory = installdir + "Drivers"

Dim InstallUtilPath
'InstallUtilPath = "rundll32 syssetup,SetupInfObjectInstallAction DefaultInstall 128 " + chr(34) +installdir+ "Drivers\xxx.inf" + chr(34)
InstallUtilPath = "rundll32 syssetup,SetupInfObjectInstallAction DefaultInstall 128 .\xxx.inf" 
MsgBox InstallUtilPath
WshShellInstallTest.Run InstallUtilPath , 0, true
if (Err.Number <> 0) Then
MsgBox "WshShell" & Err.Number & " " & Err.Description
Err.Clear
end if

set WshShellInstallTest = nothing

End Function



Function UnInstallDriver()
on error resume next
Dim WshShellInstallTest, oExec ,windowsdir
Set WshShellInstallTest = CreateObject("WScript.Shell")
if (Err.Number <> 0) Then
MsgBox "WScript.Shell" & Err.Number & " " & Err.Description
Err.Clear
end if
Dim installdir
installdir = Session.Property("CustomActionData")
if (Err.Number <> 0) Then
MsgBox "CustomActionData" & Err.Number & " " & Err.Description
Err.Clear
end if
WshShellInstallTest.CurrentDirectory = installdir + "Drivers"
Dim InstallUtilPath
InstallUtilPath = "Fltmc unload bfaccess"
WshShellInstallTest.Run InstallUtilPath , 0, true
InstallUtilPath = "rundll32 setupapi,InstallHinfSection DefaultUninstall 132 " +chr(34) + installdir +"Drivers\xxx.inf" + chr(34)
if (Err.Number <> 0) Then
MsgBox "WshShell" & Err.Number & " " & Err.Description
Err.Clear
end if

set WshShellInstallTest = nothing

End Function

Thursday, February 27, 2014

About Msi Installer impersonate problem.

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 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());
  
  
  }

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
Here's the situation:
  1. 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.
  2. You want to have multiple workers processing these messages to improve efficiency and performance of long-running processing on large numbers of messages.
  3. When you shutdown, you want all the processing code to complete before allowing the process to exit.
The first item can be accomplished with using MessageQueue's BeginPeek method and PeekCompleted event. This will allow you to peek at the queue and and begin a transaction before actually receiving the message. Beginning a transaction before receiving the message allows you to abort the transaction should an error occur during processing, leaving the message on the queue to be processed again later (hopefully with a higher chance of success). The following event handler shows the boilerplate code to accomplish this:
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;
        }
    }
}

Friday, January 31, 2014

Could not load type 'System.ServiceModel.Activation.HttpModule'

I have a test machine,  IIS installed,
My web application installed there, it was running well.
Later, I install the VS2010. try trace code.
I change the web site map path. Build application .
when try load page . Got Could not load type 'System.ServiceModel.Activation.HttpModule'
fix by : http://msdn.microsoft.com/en-us/library/hh169179(v=nav.71).aspx
cd\Windows\Microsoft.NET\Framework64\v4.0.30319
aspnet_regiis.exe -iru
iisreset