Monday, February 6, 2012

How to add options to a Setup and Deployment project in Visual Studio

Visual Studio has a "Setup and Deployment" project, that is mostly easy to set up with a bunch of clicks.

If you want to customize the installer (with options for the user), you need to write little programs to do each custom operation.

The scripts can be written as *.exe or *.dll files, which need to be compiled. That seems a bit overkill.

The scripts can also be written as VBS (Visual Basic Scripting) language. For someone like me, I don't want to know about VBS, but that's the only other option you have. VBS is not the same as VB, but it is similar. In addition, some of the default assemblies you have access to in VBS from the command line are not available from the Setup Project.

To test out a VBS script, you run the 'cscript' command from the command line, or double click it.

Here's a VBS script that opens a firewall. You add the script to the Custom Action -> Commit, and change the CustomActionData property to [TARGETDIR]. There a bunch of variables you can pass in CustomActionData, but I've yet to find a complete list of them online.

You can make it conditional by adding something to the UserInterface (say Checkboxes (A)), name the property name of that checkbox, and then use that in a conditional for the custom action. Sorry that's vague, but should give me some hints when I actually need to implement it.


Dim target

'msgbox "start"
'msgbox Session.Property("CustomActionData")
target = Session.Property("CustomActionData")
'msgbox target

Set objFirewall = CreateObject("HNetCfg.FwMgr")
Set objPolicy = objFirewall.LocalPolicy.CurrentProfile
filename = target & "cog-trk-db-service.exe"
'msgbox filename

Set objApplication = CreateObject("HNetCfg.FwAuthorizedApplication")
objApplication.Name = "cog-trk-db-service"
objApplication.IPVersion = 2
objApplication.ProcessImageFileName = filename
objApplication.RemoteAddresses = "*"
objApplication.Scope = 0
objApplication.Enabled = True

Set colApplications = objPolicy.AuthorizedApplications
colApplications.Add(objApplication)


msgbox "Firewall exception created for " & filename
'msgbox "stop"
STM32 fault handling

http://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-fault-handler/

Here is the IAR version of the asm.


NAME HardFault_Handler

AAPCS BASE,INTERWORK
PRESERVE8
REQUIRE8

EXTERN hard_fault_handler_c

SECTION .text:CODE:REORDER(2)
THUMB

PUBLIC HardFault_Handler
PUBLIC BusFault_Handler

HardFault_Handler
BusFault_Handler
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B hard_fault_handler_c

END

Tuesday, June 28, 2011

Learning about SQL

There are more than one way to do queries in SQL in .NET. I'm summarizing them here for my own use:

  • SqlReader - reads one line of a table at a time, after a SELECT statement is made
  • SqlDataAdapter -still learning about this. appears to be a magic box where things just happen.
  • Linq - DataContext - uses high level LINQ statements to do the query. Has the advantage of mostly keeping things tightly typed. Has the disadvantage that it doesn't do generic SQL commands (like add a new column to a table).

Friday, June 11, 2010

C# example of directly getting the local time from a Domain Controller

In case you need to get the current time (appears to be UTC) from a trusted source rather than rely on the local computer to report the time (which can be easily changed), this snippet gives guidance. You can get the name of a domain controller from the LOGONSERVER environment variable.


using System.DirectoryServices.ActiveDirectory;

DirectoryContext context = new
DirectoryContext(DirectoryContextType.DirectoryServer, "insert_domain_controller_name_here");
DomainController dc =
DomainController.GetDomainController(context);
DateTime dt = dc.CurrentTime;
MessageBox.Show("Domain Time is " +
dt.ToLongTimeString());

Monday, August 24, 2009

Puzzler #1


unsigned char x = 0x80;

main (void) {
char y;

y = 0x80;
if (x != y) {
printf("This should not happen\n");
}
}


Why does the string "This should not happen" appear on the console? It does on VS2005 for x86, but may not on a 8051 processor.

Answer: The problem is that 'char' and 'unsigned char' are different when it comes to comparisons, and that compilers like to optimize the comparison using machine register sizes. C casts the operands to machine sizes: unsigned char 0x80 gets cast to 0x00000080, and signed char 0x80 gets cast to 0xFFFFFF80. Then when you compare them, they don't equate! ARGH....

Thursday, August 20, 2009

Using Bits in 8051 assembly

warning: this is a placeholder written from memory. I need to update it



Useful commands: The JB (Jump if Bit set) will jump if a bit is set. The encoding of the field is the bit offset from data memory address 0x20. If you forget this, and try encoding the bit directly, then you will actually get bit 0x20.0 + 0x20 = 0x24.0 (ie 32 bits down the line).

To declare the bit in ASM:


BSEG 0 ; offset 0 in the 0x20.0 to 2F.7 range.
BIT mybit ; declare mybit at 0x20.0
...

; useful 8-byte entry in the vector table (ie at offset 0x0003 in code space for an ISR)

CSEG AT 0x0003

JB mybit, passhop ; 3 bytes encoding
AJMP fail ; 2 bytes encoding
passhop: LJMP pass ; 3 bytes encoding = 8 bytes total



In C, you would declare the bit as:

extern bit myBit at 0x20;

How to read high resolution system time in Win32


// example of how to read the system clock.
SYSTEMTIME st;
::GetSystemTime(&st);
FILETIME ft;
::SystemTimeToFileTime(&st,&ft);
DWORD diff = ft.dwLowDateTime - lasttime;
double rate;
rate = DEF_BUF_SIZE * 1000.0 / (diff * 1e-7) ;
std::cout << " rate:" << rate << std::endl;
lasttime = ft.dwLowDateTime;