Sunday, April 17, 2011

How to get the installation directory?

The MSI stores the installation directory for the future uninstall tasks.

Using the INSTALLPROPERTY_INSTALLLOCATION property (that is "InstallLocation") works only the installer has set the ARPINSTALLLOCATION property during the installation. But this property is optional and almost nobody uses it.

How could I retrieve the installation directory?

From stackoverflow
  • Use a registry key to keep track of your install directory, that way you can reference it when upgrading and removing the product.

    Using WIX I would create a Component that creates the key, right after the Directy tag of the install directory, declaration

    Michael Damatov : I haven't done it, so I still need to know how get the directory...
    CheGueVerra : What are you using to create the MSI file with, every language would have it's specifications to get that information
    Michael Damatov : I've made it with InstallShield 11.5 (I know it's outdated...). BasicMSI project.
  • I would try to use Installer.OpenProduct(productcode). This opens a session, on which you can then ask for Property("TARGETDIR").

    Michael Damatov : Already tried: doesn't work
  • Try this: var sPath = this.Context.Parameters["assemblypath"].ToString();

  • I'd use MsiGetComponentPath() - you need the ProductId and a ComponentId, but you get the full path to the installed file - just pick one that goes to the location of your installation directory. If you want to get the value of a directory for any random MSI, I do not believe there is an API that lets you do that.

xmodem for python

Hi All:

I am wiriting a program that requires the use of XMODEM to transfer data from a sensor device. I'd like to avoid having to write my own XMODEM code, so I was wondering if anyone knew if there was a python XMODEM module available anywhere?

Al

From stackoverflow
  • I think you’re stuck with rolling your own.

    You might be able to use sz, which implements X/Y/ZMODEM. You could call out to the binary, or port the necessary code to Python.

  • Here is a link to XMODEM documentation that will be useful if you have to write your own. It has detailed description of the original XMODEM, XMODEM-CRC and XMODEM-1K.

    You might also find this c-code of interest.

  • You can try using SWIG to create Python bindings for the C libraries linked above (or any other C/C++ libraries you find online). That will allow you to use the same C API directly from Python.

    The actual implementation will of course still be in C/C++, since SWIG merely creates bindings to the functions of interest.

  • def xmodem_send(serial, file):
    t, anim = 0, '|/-\\'
    serial.setTimeout(1)
    while 1:
        if serial.read(1) != NAK:
            t = t + 1
            print anim[t%len(anim)],'\r',
            if t == 60 : return False
        else:
            break
    
    p = 1
    s = file.read(128)
    while s:
        s = s + '\xFF'*(128 - len(s))
        chk = 0
        for c in s:
            chk+=ord(c)
        while 1:
            serial.write(SOH)
            serial.write(chr(p))
            serial.write(chr(255 - p))
            serial.write(s)
            serial.write(chr(chk%256))
            serial.flush()
    
            answer = serial.read(1)
            if  answer == NAK: continue
            if  answer == ACK: break
            return False
        s = file.read(128)
        p = (p + 1)%256
        print '.',
    serial.write(EOT)
    return True
    

Java array: direct access to component in array

Am I able to access an array component directly such as:

String x = args[1] ?

or do I have to use a loop and use args[i] ?

From stackoverflow
  • Yes, you can access an array component directly.

    For example:

    String[] test = new String[] { "first", "second" };
    System.out.println(test[1]); // Prints second
    

    (EDIT: For some reason I was sure this was about JavaScript not Java. Bizarre.)

  • Surely you can use args[1] too.

  • yes. You can do that, assuming args[1] exists, otherwise you'll get an ArrayIndexOutOfBoundsException.

  • What makes you think you can not?

Implementing a strategy for the constructor

What is the best way to implement a strategy for the constructor of a template/abstract class in C#? I have several classes which are all based on parsing a string inside the constructor. The parsing is done in a static method which creates list of key value pairs and is common for all classes, but some fields are also common for all classes - thus I use a abstract template class.

The problem is that I do not see a way to inherite the implementation of the constructor of the abstract base class. Otherwise I would implement the constructor strategy in the base class and would force the handling of the lists inside some abstract methods.

Edit: Added Not working code for the template class

public abstract class XXXMessageTemplate 
{
    public XXXMessageTemplate(string x) // implementation for the constructor 
   {
       Parse(x);//general parse function
       CommonFields();//filling common properties
       HandlePrivateProperties();//fill individual properties
       HandlePrivateStructures();//fill individual structures
    }
    abstract void HandlePrivateProperties();
    abstract void HandlePrivateStructures();
}

The actual messages should not implement any constructor and only implement the HandlePrivateProperties and HandlePrivateStructures functions.
From stackoverflow
  • If you want the logic of the base class constructor to run in the derived class, you'd normally just call up to it:

     public Derived(...) : base(...)
     {
         // ...
     }
    

    The base class can call abstract/virtual methods during the constructor, but it's generally frowned upon as the derived class's constructor body will not have been executed yet. (You'd want to document this really emphatically.)

    Does this answer your question? I'm not entirely sure I understand the issue - some pseudo-code would help.

    EDIT: The derived classes have to implement constructors. Constructors aren't inherited. If you don't specify any constructor, the compiler will provide a parameterless constructor which calls a base parameterless constructor. However, you can easily write a constructor with the same signature and just call the base class constructor:

    public Derived(string x) : base(x)
    {
        // Base constructor will do all the work
    }
    
    weismat : I have added some pseudo-code to make the issuer cleaner...
    weismat : Ok - this means my intension is impossible to force the strategy pattern here - I have to implement then a constructor which calls a protected function name constructor which calls then the Handle functions. Reminds me of the restriction that a constructor can no call another constructo of a class.
    Jon Skeet : Constructors can call constructors of other classes - you can write "object o = new object()" for instance. You can't try to use another constructor as part of your own constructor chain though - that wouldn't make much sense.
    Jon Skeet : Another option would be to encapsulate the strategy in a separate interface, and pass that interface into the constructor - don't bother with the derived classes at all.
  • Provide a constructor for the base class and use it in the derived classes:

    abstract class Base {
         // ...
         protected Base(string commonField) {
            CommonField = commonField;
         }
    }
    
    class Derived1 : Base {
         public Derived1(string commonField, string specificField) : base(commonField) {
            SpecificField = specificField;
         }
    }
    
  • I am not 100% sure I understand the question fully, but do you mean that you want your subclasses to pass a literal string to the base, as in this example?

    public class MyMessage : XXXMessageTemplate
    {
        public MyMessage() : base("MyMessage String")
        {
        }
    
        public override void HandlePrivateProperties()
        {
            // ...
        }
    
        public override void HandlePrivateStructures()
        {
            // ...
        }
    }
    
  • As I can see the problem is in Parse(...) method. Not in the method itself but in his existence. You have some raw data (string x) which must be converted into structured data (key value pairs) before use to construct objects. So you need somehow pass structured data into base and child constructors. I see 3 approaches:

    1. Parse data in base class and use protected base property to pass it to childs.
    2. Parse data before calling constructor.
    3. Parse data in place of usage.

    1 You may extend an Mehrdad answer via additional protected property which holds parsed args. Something like:

    abstract class Base {
         protected ParsedData ParsedData;
         // ...
         protected Base(string x) {
            ParsedData = Parse(x);
            CommonFields(); //initialize common fields using ParsedData
         }
    }
    
    class Derived1 : Base {
         public Derived1(string x) : base(x) {
            DerivedFields(); //initialize specific fields using ParsedData
         }
    }
    

    2 Or you can pass pre parsed string into constructor:

    abstract class Base {
         protected ParsedData ParsedData;
         // ...
         public static ParsedData Parse(string x)
         {
            //Parse x here...
         }
    
         protected Base(ParsedData data) {
            CommonFields(data); //initialize common fields using data
         }
    }
    
    class Derived1 : Base {
         public Derived1(ParsedData data) : base(data) {
            DerivedFields(data); //initialize specific fields using data
         }
    }
    

    3 Or parse in place of usage:

    abstract class Base {
         // ...
         protected Base(string x) {
            var data = Parse(x);
            CommonFields(data); //initialize common fields using data
         }
    }
    
    class Derived1 : Base {
         public Derived1(string x) : base(x) {
            var data = Parse(x);
            DerivedFields(data); //initialize specific fields using data
         }
    }
    
    weismat : Interesting approach - the parse method is actually currently in the Base Class and the resulting object is not kept - to some degree also to memory restrictions. I am surprised that you dam the parse function as the issue, but it sounds logical.
    Aleksei : Sorry, forget to mention method #1 disadvantage: parsed data will remain until object GCed. Also there is no easy way to clear that field, because at some particular constructor you do not know, whether another one child exists or not.

Quickest way to set properties on an object?

Assume you have a business object with a lot of properties. What is the easiest and best way to set the properties without the use of an ORM tool?

This implies setting properties from a data reader object, such as

client.Name = (string)reader["Name"];

What about the case where the object contains other complex objects?

Any suggestions?

From stackoverflow
  • Serialization and/or Reflection is an option.

    sduplooy : Reflection poses a problem where the column name does not match the objects corresponding property name.
    Sandy : Unless you specify a mapping between column names and property names, you can't achieve what you want. Specifying such a mapping brings you to building a custom ORM, or using an existing one.
  • Well, you could use reflection to generate the assignation code.

  • You ask for three different things:

    • quickest
    • easiest
    • best

    they are not the same! The quickest (at execution) would be compiled code; i.e. you write regular C# to set the properties correctly. Easier than this is using reflection - but that is slow. You'd also need some mechanism for mapping child properties... (and also mapping regular properties if there isn't a 1:1 correspondance between the reader). This is perhaps best solved with custom attributes on members (properties/fields).

    As a compromise on speed (over reflection), you can use Delegate.CreateDelegate to get at the property setters - but that is a lot of work. Perhaps another option is HyperDescriptor; this allows reflection-like access, but is vastly faster.

    Best? Probably to use existing code - i.e. an ORM tool; less to write and debug.

    Brann : well, I guess by quickest, he meant quickest to write, not quickest to execute.

Spring Hibernate SQL Query

I have a VO class which has the getter and setter of another VO class too. For example:

Class DocumentVO{
   PrintJobVO job;
   PrintRunVO run;
   String id;
   getters and setters..
}

Now I have a requirement to use the Native SQL Query using spring hibernate. When I want to map the ids I have a problem. My query is,

select {r.*},{d.*}
from runs {r}, documents {d}
where {r}.RUN_ID as {r.id} = d.RUN_ID as {d.run.id}

Here run is of type PrintRunVO which has its id and other values. How can I map them in my SQL? I am getting an error like invalid user.table.column, table.column, or column specification.

What's the way to overcome this?

From stackoverflow
  • Use the Result Transformer concept in your plain SQL query.

    String query = "myquery";
    SQLQuery q = session.createSQLQuery(query);
    q.addScalar("param1", Hibernate.STRING);
    q.addScalar("param2", Hibernate.STRING);
    q.setResultTransformer(Transformers.aliasToBean(MyVO.class));
    q.setParameter("queryParam1", "some value");
    return q.list();
    

RunTime Error '70' Permission Denied in VB6

Hi, I am using VB6. The tool that i have created extracts few zip files and unzips them onto a folder that i create locally.In the clean up part of my code, i have deleted the folder using this code

If (f.FolderExists(path + "Extracted Files") = True) Then
     f.DeleteFolder (path + "Extracted Files")
End If

When i run this code, i get an error Run Time Error '70' and Permission Denied in the line f.DeleteFolder(path + 'Extracted Files').

Where am i going wrong ? Or do i need to create the folder with a different permission ?

From stackoverflow
  • Do you still have one of the files in this folder open in your code somewhere?

  • no i do not have any of the files from that folder open

  • Perhaps one or more of the files is read-only? Use the optional force parameter to force deletion:

    f.DeleteFolder (path + "Extracted Files"), True
    
  • hey raven, thanks for that suggestion !!!! it seems to have worked !!!