RegDBKeyExists function fails to read in Installshield - installshield-2011

We have developed MSI package in Installshiled 2008 Premier Edition and project type is Installscript MSI, recently we bought 2011 and upgrdaded our project to 2011.
In earlier version we used to check the registry entries for Microsoft SQL Express and its path is
**HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL**
Now a new require came to create a package for 64 bit O.S., since O.S. is 64-bit but the registry path for SQL Express in 64 bit is
**HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server\Instance Names\SQL**
The registry function RegDBKeyExists is to check SQL registry's presence, but function is returning a negative number as -2147483646 and fails to read.
setting the option REGDB_OPTIONS = REGDB_OPTIONS | REGDB_OPTION_WOW64_64KEY will not help because we not reading 64 bit related registry Hive.

Don't worry about it so much; Registry Reflection makes this do the right thing without extra code. When a 32-bit app accesses HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL on a 64-bit machine it will be redirected and see HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server\Instance Names\SQL (unless it passes the KEY_WOW64_64KEY - equivalent to the REGDB_OPTION_WOW64_64KEY).
If you hardcode the Wow6432Node key into your query, this scenario will tend to see the keys under a path including HKLM\Software\Wow6432Node\Wow6432Node\... and be unable to find the key you meant to find.

As a follow up to Michael's answer and my comment (i.e. question), here's an InstallScript function to toggle registry reflection:
prototype void EnableRegistryReflection( BOOL );
///////////////////////////////////////////////////////////////////////////////
//
// Function: EnableRegistryReflection
//
// Purpose: Toogle the automatic conversion of registry keys from 64 to 32 bit equalivents.
// This is enabled by default.
//
///////////////////////////////////////////////////////////////////////////////
function void EnableRegistryReflection( bEnable )
begin
if( bEnable ) then
REGDB_OPTIONS = REGDB_OPTIONS & ~REGDB_OPTION_WOW64_64KEY;
else
REGDB_OPTIONS = REGDB_OPTIONS | REGDB_OPTION_WOW64_64KEY;
endif;
end;

Related

What does SQLEXPR Installer return code -2068578304 mean?

I am working on an installer project where we are replacing an old WISE based installer with innosetup.
One of the install scripts that is being ported to the new installer kicks of SQLEXPR.exe which is SQL Server Express.
During testing some computers get %ERRORLEVEL% = -2068578304
A bit of googling and I have been unable to work out the exact meaning. This is not in the range of error codes produced by MSI based installers. Does anyone have any idea what the cause of error here is and how to correctly parse it? I am seeing other large negative error codes that can be split into multiple pieces. e.g. exit code and facility code? any ideas?
After finding the log file, I've found a bit more info. And when converting that number to hex I can now see the problem. The batch file that is used to kick off the SQL Server Express installation is treating the result as a 32bit number but it's really a 16bit one. So if I mask -2068578304 to 0xffffffff
I will get the result 0x84b40000. The script looks currently looks at the bottom 4 bits to determine error or success (this is zero) so the question now becomes what does the Facility Code mean? as it appears it largely installed but the default instance is missing.
I guess I'm really wanting to know what values Facility Code can be returned. Our installation script is just looking at ErrorCode but that is not enough in other words. Is there a list of descriptions somewhere for FacilityCode?
Update:
It turns out that this is a problem with SQL2012 and earlier that the actual ErrorCode is not propagated to the SQLEXPR return code. It should really return the inner result 0x851a0013. SQL2014 and newer does the right thing.
Exception summary:
The following is an exception stack listing the exceptions in outermost to inner
most order
Inner exceptions are being indented
Exception type: Microsoft.SqlServer.Chainer.Infrastructure.InputSettingValidatio
nException
Message:
The specified sa password does not meet strong password requirements. Fo
r more information about strong password requirements, see "Database Engine Conf
iguration - Account Provisioning" in Setup Help or in SQL Server 2012 Books Onli
ne.
HResult : 0x84b40000
FacilityCode : 1204 (4b4)
ErrorCode : 0 (0000)
Data:
SQL.Setup.FailureCategory = InputSettingValidationFailure
DisableWatson = true
Stack:
at Microsoft.SqlServer.Chainer.Infrastructure.InputSettingService.LogAll
ValidationErrorsAndThrowFirstOne(ValidationState vs)
at Microsoft.SqlServer.Configuration.SetupExtension.ValidateFeatureSetti
ngsAction.ExecuteAction(String actionId)
at Microsoft.SqlServer.Chainer.Infrastructure.Action.Execute(String acti
onId, TextWriter errorStream)
at Microsoft.SqlServer.Setup.Chainer.Workflow.ActionInvocation.ExecuteAc
tionHelper(TextWriter statusStream, ISequencedAction actionToRun, ServiceContain
er context)
Inner exception type: Microsoft.SqlServer.Configuration.SqlEngine.Validation
Exception
Message:
The specified sa password does not meet strong password requirem
ents. For more information about strong password requirements, see "Database Eng
ine Configuration - Account Provisioning" in Setup Help or in SQL Server 2012 Bo
oks Online.
HResult : 0x851a0013
FacilityCode : 1306 (51a)
ErrorCode : 19 (0013)

ActiveX component can't create object: 'TDApiOle80.TDConnection'

I am trying to connect to QCServer using Excel Macro. I am using a 64-bit operating system with following being done:
Register OTAClient.dll
Installed HP ALM Connectivity tool
Added OTA Library to reference
I am getting the following error:
ActiveX component can't create object: 'TDApiOle80.TDConnection'
But the same is running using VBScript:
C:\Windows\SysWOW64\Wscript.exe "C:\Users****\Desktop\qcConn.vbs"
I have found this solution on some other blog:
If you are on 64 bit machine, by default your script will run with the 64 bit version of wscript.exe. But QC is a 32 bit app, so you need to consume it from a 32 bit version of wscript.exe which is located at c:\Windows\SysWOW64\wscript.exe.
So what can be done to run it, call command line prompt in your macro and run your command:
C:\Windows\SysWOW64\Wscript.exe
C:\Users****\Desktop\qcConn.vbs
which will call that vbs. Eg:
Dim goWS: Set goWS = CreateObject("WScript.Shell")
sCmd = "C:\Windows\SysWOW64\Wscript.exe "C:\Users****\Desktop\qcConn.vbs""""
Set oExec = goWS.Exec(sCmd)
Hope this helps !!
This is due to the COM objects issue, you need to create few Key's in Registry to run it without issues.
1) Locate your COM object (TDAPIOLE80) GUID under the HKey_Classes_Root\Wow6432Node\CLSID[GUID]
Once located (in the parent folder) add a new REG_SZ (string) Value. Name should be AppID and data should be the same COM object GUID (Along with {}) you have just searched for.
2) Add a new key under HKey_Classes_Root\Wow6432Node\AppID\, the new key should be called the same as the com object GUID (Along with {})
3) Under the new key you just added, add a new string (REG_SZ) Value, and call it DllSurrogate, Leave the value empty
4) Create a new Key under HKey_Local_Machine\Software\Classes\AppID\ , Again the new key should be called the same as the COM object’s GUID (Along with {}). No values are necessary to be added under this key.
With this you should be good!!
Cheers!!
You can also try following steps-
1.Open IE as Admin(right click on IE Run as Administrator)
2.Open ALM, Navigating by URL (your url)
3.Click on Tools link
4.Click on ALM Connectivity link (Run your download)
5.again Click on Tools
6.HP ALM Client Registration Link
4.In the pop up scroll down and select ‘Register HP ALM’
5.It’ll do some downloads. Once completed close the window
This will fix the problem.

creating xml file using c# and oracle

I have to generate set of xml files by querying oracle db table based on some condition.
the xml file structure little complex and their is a limit on file size if limit croees new file need to be created. what is the best approch to this. using select XMLElemnt in oracle plsql or doin it in C# after querying data from db using cursor?
performamce also to be considered and this process need to be done faster.
In oracle 11.2 you can transform the results from a ref cursor into a XML(CLOB) using dbms_xmlgen.
EXAMPLE:
PROCEDURE GetXMLByRefCursor
(
irfCursor in REF CURSOR,
oclXMLDocument out nocopy clob,
isbRootTag in varchar2 default null,
isbResultTag in varchar2 default null,
inuNullHandling in number default dbms_xmlgen.DROP_NULLS
)
IS
nuContext dbms_xmlgen.ctxHandle;
BEGIN
nuContext:= dbms_xmlgen.newContext(irfCursor);
dbms_xmlgen.setPrettyPrinting(nuContext, false);
dbms_xmlgen.setNullHandling(nuContext, inuNullHandling);
if (isbRootTag is not null) then
dbms_xmlgen.setRowSetTag(nuContext, isbRootTag);
end if;
if (isbResultTag is not null) then
dbms_xmlgen.setRowTag(nuContext, isbResultTag);
end if;
oclXMLDocument := dbms_xmlgen.getXML(nuContext);
dbms_xmlgen.closeContext(nuContext);
END GetXMLFromRefCursor;
In PLSQL you cannot easily manage resulting XML size.
Performance-wise, it can be better either in PLSQL or in C#, that depends on the speed of the .NET-side machine and the speed of the OracleDB-side machine.
Also, if you create XML in PLQSL and then return in to the caller C# tier, you'll have to do it via CLOBs. Since this would involve temporary CLOBs, some copying in the Oracle's temp tablespace might be involved, thus decreasing performance.
All in all, I suggest doing it rather in C#.

Entity Framework & Oracle: Cannot Insert VARCHAR2 > 1,999 Characters

I created a 4,000-character VARCHAR2 field in an Oracle table. I am inserting string values into the field using LINQ to Entities with Visual Studio 2010, .NET Framework 4, and ODAC 11.2 Release 4 and Oracle Developer Tools for Visual Studio (11.2.0.3.0). When I try to insert a string value greater than 1,999 characters, I get the following inner exception:
Oracle.DataAccess.Client.OracleException
ORA-00932: inconsistent datatypes: expected - got NCLOB
However, I can insert a 4,000 character string value into the field without any issue when doing so using SQL Developer.
There is a known ODAC bug (source #2) in which there is a 2,000 character limit when saving to an XMLTYPE field, but I am not saving to an XMLTYPE field. I have Oracle.DataAccess 2.112.3.0 in my GAC, and I considered updating to release 5 (11.2.0.3.20) of the aforementioned Oracle software, but "Oracle Developer Tools for Visual Studio" is the only component that appears to have been updated from release 4, and I believe that "Oracle Data Provider for .NET 4" is the component that needs updating. In my .NET project, System.Data.Entity and System.Data.OracleClient are both runtime version 4.0.30319.
Anyway, I am just wondering if anyone else has encountered this error, and if so, if any solution has been found - aside from the one in the Oracle forum thread that is linked above that proposes using stored procedures as a workaround. Google tells me that people are encountering this error only when working with XMLTYPE fields, but I can't be the only person who is encountering this error when working with a VARCHAR2 field, can I?
(FWIW, I am also hoping to receive a response to my post as user "997340" in the Oracle forum thread that is linked above. If I receive a useful response, I'll be sure to share the knowledge on this end.)
EDIT: In case it helps, below are the two blocks in my code that are failing. I created the second block when troubleshooting the first, just to see if there was any difference. I get the exception when checking to see if the string values were already inserted (the "if" statements), and when actually inserting the string values (the "AddObject" statements).
1:
if (!(from q in db.MSG_LOG_MESSAGE where q.MESSAGE == msg select q.MESSAGE).Any())
{
db.MSG_LOG_MESSAGE.AddObject(new MSG_LOG_MESSAGE { MESSAGE = msg });
db.SaveChanges();
}
2:
if (!db.MSG_LOG_MESSAGE.Any(q => q.MESSAGE == msg))
{
db.MSG_LOG_MESSAGE.AddObject(new MSG_LOG_MESSAGE { MESSAGE = msg });
db.SaveChanges();
}
APRIL 3 UPDATE:
I was able to trace the SQL that is being sent to Oracle from the "if" statement in the first code block above. Here it is:
SELECT
CASE WHEN ( EXISTS (SELECT
1 AS "C1"
FROM "SEC"."MSG_LOG_MESSAGE" "Extent1"
WHERE ("Extent1"."MESSAGE" = :p__linq__0)
)) THEN 1 WHEN ( NOT EXISTS (SELECT
1 AS "C1"
FROM "SEC"."MSG_LOG_MESSAGE" "Extent2"
WHERE ("Extent2"."MESSAGE" = :p__linq__0)
)) THEN 0 END AS "C1"
FROM ( SELECT 1 FROM DUAL ) "SingleRowTable1" ;
Unfortunately, the DBA that I worked with did not provide me with the value of the "p_linq_0" parameter, but as previously stated, when it is over 1,999 characters, an exception occurs. (When this SQL was traced, I passed a 4,000-character string as the parameter, and of course an exception occurred.) The DBA also mentioned something about certain SQL clients - such as SQLPlus - not being able to handle VARCHAR2s over 2,000 characters. I did not entirely follow. Whether using SQLPlus, SQL Developer, or any other tool, Oracle is still going to be querying a 4,000-character VARCHAR2 field. Plus, my magic number is 1,999 characters; not 2,000 characters. Did the DBA perhaps mean there is a limitation with how many characters can be in a parameter? More importantly, when I execute this SQL in SQL Developer and I enter a 4,000-character string for the parameter, it works perfectly. So I am still utterly confused about why it is not working via LINQ to Entities. I also tried the following code in my program to run a similar query with a 4,000-character string in the "msg" variable, which worked perfectly as well:
using Oracle.DataAccess;
using Oracle.DataAccess.Client;
using System.Data;
...
OracleConnection conn = new OracleConnection("Data Source=[MASKED];User Id=[MASKED];Password=[MASKED]");
conn.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT message FROM msg_log_message WHERE message = '" + msg + "'";
cmd.CommandType = CommandType.Text;
OracleDataReader dr = cmd.ExecuteReader();
dr.Read();
string result1 = dr.GetString(0);
conn.Dispose();
For now, I am still pointing fingers at ODAC being buggy as it pertains to LINQ to Entities...
The latest ODP.NET documentation - for "11.2 Release 5 Production (11.2.0.3.0)" from September 2012 - states the following known issue under the "Entity Framework Related Tips, Limitations and Known Issues" section, which addresses the error from the "if" statements in the question's code blocks:
An "ORA-00932 : inconsistent datatypes" error can be encountered if a string of 2,000 or more characters, or a byte array with 4,000 bytes or more in length, is bound in a WHERE clause of a LINQ/ESQL query. The same error can be encountered if an entity property that maps to a BLOB, CLOB, NCLOB, LONG, LONG RAW, XMLTYPE column is used in a WHERE clause of a LINQ/ESQL query.
Older ODP.NET documentation - for "Release 11.2.0.3.0 Production" from May 2011 - states the same known issue, so apparently this has been a known issue for a while.
Neither of the aforementioned documentation mentions encountering the same error from the "AddObject" statements in the question's code blocks, but that issue is very similar to another known issue for XMLType fields that is mentioned:
An "ORA-00932: inconsistent datatypes: expected - got NCLOB" error will be encountered when trying to bind a string that is equal to or greater than 2,000 characters in length to an XMLType column or parameter. [Bug 12630958]

Not able to delete key with RegDBDeletekey using InstallShield

I am new to this InstallShield code.
I am trying to delete a key with
RegDBDeleteKey("Nrs_Log");
But was not able to delete and setup is running fine.
Could anyone suggest any other way to delete a registry key.
There are many reasons why a RegDBDeleteKey() might fail. There is not enough info in your post to determine the problem, so I can't even speculate without more information. So here is how to get more information - You need to get the return value of the RegDBDeleteKey() call, so you can find out what is going on.
The below code gets the return value, converts it to a text error, and displays the result.
result = RegDBDeleteKey("Nrs_Log");
if(result < 0) then
SprintfBox(WARNING, "RegDBDelete...", "Failed to delete registry key.\n Error number: %d \n %s", result, FormatMessage(result) );
endif;
Once you know the actual error, you should be able to fix the problem or Google it for more info.
Please refer to below InstallShield InstallScript on how you can delete a given registry hive. If checks whether the registry key exists or not before trying to delete it:
function DeleteRegistryKeys(hMSI)
STRING keyToDelete;
begin
keyToDelete = "\\SOFTWARE\\MyRegistryHive\\";
//comment below line if your target root hive is HKEY_CLASSES_ROOT
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); //Set this if you want to change the registry root to HKEY_LOCAL_MACHINE.
REGDB_OPTIONS = REGDB_OPTION_WOW64_64KEY; //Set this only if you want to search WOW64 hive of HKEY_LOCAL_MACHINE if you've a 32-bit installer running on a 64 bit operating system.
if (RegDBKeyExist (keyToDelete) > 0) then
SprintfMsiLog ("registry keys found. Going to delete registry keys");
if (RegDBDeleteKey (keyToDelete) < 0) then
SprintfMsiLog ("Failed to delete registry keys.");
else
SprintfMsiLog ("Registry keys deleted successfully.");
endif;
else
SprintfMsiLog ("Registry keys not found.");
endif;
end;

Resources