I created an ADO.NET Entity Data Model, using this instruction. I have two new classes:
namespace Parser
{
public partial class advert : EntityObject
{
///////////
}
public partial class test_workEntities1 : ObjectContext
{
///////
}
}
Then I created the following class:
namespace Parser
{
public class BdProvider
{
public void InsertAdv()
{
advert adv = new advert();
test_workEntities1 f = new test_workEntities1();
adv.adress = "adress 1";
adv.const_link = "domain.com";
adv.count_room = 10;
f.advert.AddObject(adv);
}
}
}
And I have created the following console application:
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
BdProvider bd = new BdProvider();
bd.InsertAdv();
Console.ReadKey();
}
}
}
When I run the application, I see:
The specified named connection is either not found in the
configuration, not intended to be used with the EntityClient provider,
or not valid
StackTrace:
System.ArgumentException не обработано Message=Указанное именованное
соединение не найдено в конфигурации, не предназначалось для
использования с поставщиком EntityClient или недопустимо.
Source=System.Data.Entity StackTrace: в
System.Data.EntityClient.EntityConnection.ChangeConnectionSt
ring(String newConnectionString) в
System.Data.EntityClient.EntityConnection..ctor(String
connectionString) в
System.Data.Objects.ObjectContext.CreateEntityConnection(Str ing
connectionString) в System.Data.Objects.ObjectContext..ctor(String
connectionString, String defaultContainerName) в
Parser.test_workEntities1..ctor() в
C:\proj\Parser\Model1.Designer.cs:строка 34 в
Parser.BdProvider.InsertAdv() в C:\proj\Parser\BdProvider.cs:строка 28
в TestApp.Program.Main(String[] args) в
C:\proj\TestApp\Program.cs:строка 21 в
System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[]
args) в System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence
assemblySecurity, String[] args) в
Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssem bly() в
System.Threading.ThreadHelper.ThreadStart_Context(Object state) в
System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state, Boolean
ignoreSyncCtx) в
System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state) в
System.Threading.ThreadHelper.ThreadStart() InnerException:
I tried to create test_workEntities1, using different connectionString, but I was not successful.
My connectionString is
<connectionStrings>
<add name="test_workEntities1"
connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string="Data Source=PKVZALE\SQLEXPRESS;Initial Catalog=test_work;Integrated Security=True;MultipleActiveResultSets=True""
providerName="System.Data.EntityClient" />
</connectionStrings>
You need to add the connection string the TestApp configuration file.
Currently, you have it in the app.config file of the Parser project, however, as you are running the application via the TestApp project, .NET is looking for settings in this project.
// Expanded Answer
The app.config can be created in the root folder of your project. You can do this by copy/paste from Parser project or by using the following instructions from msdn
To add an application configuration file to your C# project
On the Project menu, click Add New Item.
The Add New Item dialog box appears.
Select the Application Configuration File template and then click Add.
A file named app.config is added to your project.
You need to do 3 things when you have an entity framework - EF in a different project:
Connection String in EF project
Reference in another project
EF Connection string in another project
Related
I am pretty new to C# and .net. and I have been tasked with creating a WPF application POC to read a QTP object repository in a .tsr file and populate a TreeView with all the objects in that repository and their child objects.
I was provided with QTP's RepositoryUtil.dll and the following sample code to adapt to C#:
Dim i
Dim ORFile = "D:\TAF\Size.tsr"
Dim ORObj = CreateObject("Mercury.ObjectRepositoryUtil")
ORObj.Load(ORFile)
Dim ObjectCollection = ORObj.GetChildren
For i = 0 To ObjectCollection.Count - 1
Dim Obj = ObjectCollection.Item(i)
Dim temp1 = "" & Obj.GetTOProperty("micclass") & "(""" & ORObj.GetLogicalName(Obj) & """)"
Dim treeItem = New TreeViewItem
Dim tNode = New TreeViewItem() With {.Header = temp1}
treeview1.Items.Add(tNode)
tNode = treeview1.Items(i)
Add(ORObj, Obj, tNode)
Next
Now I am not very familiar with Visual Basic however I am trying to adapt it as follows in a Console application to check whether the string "title" gets populated.
static void Main(string[] args)
{
string ORFilePath = #"D:\TAF\Size.tsr";
ObjectRepositoryUtil ORUtil = new ObjectRepositoryUtil();
ORUtil.Load(ORFilePath);
var ChildObjects = ORUtil.GetChildren();
for (int i = 0; i < ChildObjects.Count(); i++ )
{
var ChildObject = ChildObjects.Item(i);
string title = ChildObject.GetTOProperty("micclass") + "(\"" + ORUtil.GetLogicalName(ChildObject) + "\")";
Console.WriteLine(title);
}
}
But when I run this, I get an InvalidCastException: {"Return argument has an invalid type."} on the line "var ChildObjects = ORUtil.GetChildren();"
I cannot figure out what is wrong or what type is being returned by ORUtil.GetChildren() since there is no documentation provided with the library and I can't find any online.
So, can anyone tell what exactly am I doing wrong here and what is the proper way to go about this?
Edit:
Here's the stack trace for the above exception:
System.InvalidCastException was unhandled
HResult=-2147467262
Message=Return argument has an invalid type.
Source=mscorlib
StackTrace:
at System.Runtime.Remoting.Proxies.RealProxy.ValidateReturnArg(Object arg, Type paramType)
at System.Runtime.Remoting.Proxies.RealProxy.PropagateOutParameters(IMessage msg, Object[] outArgs, Object returnValue)
at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
at REPOSITORYUTILLib.DispIObjectRepositoryUtil.GetChildren(Object Parent)
at ORReader.Program.Main(String[] args) in c:\Users\DDDAVID.DDDAVID-IN\Documents\Visual Studio 2013\Projects\ORReader\ORReader\Program.cs:line 17
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
With some help, I've solved my own problem.
What I was trying to do was trying to add the RepositoryUtil.dll as a reference and calling its methods. What I should have been doing was to get the Program Identifier for QTP's registered ObjectRepositoryUtil using the following:
Type.GetTypeFromProgID("Mercury.ObjectRepositoryUtil");
dynamic ORUtil = Activator.CreateInstance(ORType);
I've modified the code as follows and it worked.
static void Main(string[] args)
{
Type ORType = Type.GetTypeFromProgID("Mercury.ObjectRepositoryUtil");
dynamic ORUtil = Activator.CreateInstance(ORType);
string ORFilePath = #"D:\TAF\Size.tsr";
//ObjectRepositoryUtil ORUtil = new ObjectRepositoryUtil();
ORUtil.Load(ORFilePath);
var ChildObjects = ORUtil.GetChildren();
for (int i = 0; i < ChildObjects.Count(); i++ )
{
var ChildObject = ChildObjects.Item(i);
string title = ChildObject.GetTOProperty("micclass") + "(\"" + ORUtil.GetLogicalName(ChildObject) + "\")";
Console.WriteLine(title);
}
}
This is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Text.RegularExpressions;
using System.IO;
using unfreez_wrapper;
using Shell32;
namespace DownloadImages
{
public partial class Form1 : Form
{
string f;
string UrlsPath;
int counter;
UnFreezWrapper uf;
string localFilename;
public Form1()
{
InitializeComponent();
uf = new UnFreezWrapper();
counter = 0;
localFilename = #"d:\localpath\";
UrlsPath = #"d:\localpath\Urls\";
using (WebClient client = new WebClient())
{
client.DownloadFile("http://www.sat24.com/foreloop.aspx?type=1&continent=europa#",localFilename + "test.html");
client.DownloadFile("http://www.sat24.com/en/eu?ir=true", localFilename + "test1.html");
}
f = File.ReadAllText(localFilename + "test1.html");
test("image2.ashx", "ir=true");
}
private void test(string firstTag, string lastTag)
{
List<string> imagesUrls = new List<string>();
int startIndex = 0;
int endIndex = 0;
int position = 0;
string startTag = firstTag;//"http://www.niederschlagsradar.de/images.aspx";
string endTag = lastTag;//"cultuur=en-GB&continent=europa";
startIndex = f.IndexOf(startTag);
while (startIndex > 0)
{
endIndex = f.IndexOf(endTag,startIndex);
if (endIndex == -1)
{
break;
}
string t = f.Substring(startIndex, endIndex - startIndex + endTag.Length);
imagesUrls.Add(t);
position = endIndex + endTag.Length;
startIndex = f.IndexOf(startTag,position);
}
string item = imagesUrls[imagesUrls.Count - 1];
imagesUrls.Remove(item);
for (int i = 0; i < imagesUrls.Count; i++)
{
using (WebClient client = new WebClient())
{
client.DownloadFile(imagesUrls[i], UrlsPath + "Image" + counter.ToString("D6"));
}
counter++;
}
List<string> files = Directory.GetFiles(UrlsPath).ToList();
uf.MakeGIF(files, localFilename + "weather", 80, true);
}
First im downloading this html as html file:
http://www.sat24.com/en/eu?ir=true
There there is animation of 9 different images/gifs.
I want to download each gif url. So on the hard disk i will get 9 gifs.
When reading the file http://www.sat24.com/en/eu?ir=true in the content inside i see:
var imageUrls = ["/image2.ashx?region=eu&time=201309162345&ir=true","/image2.ashx?region=eu&time=201309162330&ir=true","/image2.ashx?region=eu&time=201309162315&ir=true","/image2.ashx?region=eu&time=201309162300&ir=true","/image2.ashx?region=eu&time=201309162245&ir=true","/image2.ashx?region=eu&time=201309162230&ir=true","/image2.ashx?region=eu&time=201309162215&ir=true","/image2.ashx?region=eu&time=201309162200&ir=true","/image2.ashx?region=eu&time=201309162145&ir=true"];
And inside the List: imagesUrls i see this 9 urls:
For example this is in index 0 : image2.ashx?region=eu&time=201309162345&ir=true
I tried without the image2.ashx?
But in both cases im getting an error on the line:
client.DownloadFile(imagesUrls[i], UrlsPath + "Image" + counter.ToString("D6"));
ArgumentException
Illegal characters in path
Before this when i used the test.html and the two other tags start and end it was working without any problem.
But now im using test1.html and this two tags: test("image2.ashx", "ir=true");
But getting the exception.
When i took one image url for example : image2.ashx?region=eu&time=201309170015&ir=true
And tried to surf to it in chrome im getting no rsults it tried to search for it in google .
Its not even a url .
This is the full exception error:
System.ArgumentException was unhandled
HResult=-2147024809
Message=Illegal characters in path.
Source=mscorlib
StackTrace:
at System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional)
at System.Security.Permissions.FileIOPermission.CheckIllegalCharacters(String[] str)
at System.Security.Permissions.FileIOPermission.AddPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathListOrig, Boolean checkForDuplicates, Boolean needFullPath, Boolean copyPathList)
at System.Security.Permissions.FileIOPermission..ctor(FileIOPermissionAccess access, String[] pathList, Boolean checkForDuplicates, Boolean needFullPath)
at System.IO.Path.GetFullPath(String path)
at System.Net.WebClient.GetUri(String path)
at System.Net.WebClient.DownloadFile(String address, String fileName)
at DownloadImages.Form1.test(String firstTag, String lastTag) in d:\C-Sharp\DownloadImages\DownloadImages\DownloadImages\Form1.cs:line 79
at DownloadImages.Form1..ctor() in d:\C-Sharp\DownloadImages\DownloadImages\DownloadImages\Form1.cs:line 45
at DownloadImages.Program.Main() in d:\C-Sharp\DownloadImages\DownloadImages\DownloadImages\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Then how can i download the images one by one from this url ? http://www.sat24.com/en/eu?ir=true
When i used the test.html and the startTag ""http://www.niederschlagsradar.de/images.aspx": and endTag: ""cultuur=en-GB&continent=europa""
It worked perfect !
But now with test1.html and the two different tags its not working.
At the point of the exception, what precisely is in imagesUrls[i] ?
Are you saying that it is something like image2.ashx?region=eu&time=201309162345&ir=true
If so, you need to prepend the protocol and server to it, i.e. prepend http://www.sat24.com/ to give a URI of http://www.sat24.com/image2.ashx?region=eu&time=201309162345&ir=true
However, another problem is, you are searching for image2.ashx for a start tag and then ir=true as an end tag. Looking at the source of that page, there are numerous image2.ashx URIs which do not end with ir=true.
e.g. http://www.sat24.com/image2.ashx?button=af260x160
When you find the start tag in that URI, you're going to get an enormous mass of HTML before you find the end tag.
I have a dotnet script which is for encryption and decryption. I have to pass the parameters for the setvalues function in installshield. How can I achieve this? Dotnet code is as follows. I have the assembly (.dll) file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Security;
using System.Xml;
using System.Collections.Specialized;
namespace EncryptionDecryption
{
public class EncrptionHelper
{
#region Member variables
static byte[] entropy = { 0, 8, 2, 3, 5 };
#endregion
#region Public Methods
public static void SetValue(string configFilePathName, string appSettingKey, string appSettingValue)
{
appSettingValue = EncryptString(ToSecureString(appSettingValue));
SetSetting(appSettingKey, appSettingValue, configFilePathName);
}
public static string GetValue(string configFilePathName, string appSettingKey)
{
string value = GetSetting(appSettingKey, configFilePathName);
value = ToInsecureString( DecryptString(value));
return value;
}
#endregion
#region Private Methods
private static bool SetSetting(string Key, string Value, string configFilePath)
{
bool result = false;
try
{
// System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(configFilePath);
// config.AppSettings.File = configFilePath;
// config.AppSettings.Settings[Key].Value = Value;
// config.Save(ConfigurationSaveMode.Modified);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(configFilePath);
xmlDoc.SelectSingleNode("//appSettings/add[#key='" + Key +"']").Attributes["value"].Value = Value;
xmlDoc.Save(configFilePath);
ConfigurationManager.RefreshSection("appSettings");
result = true;
}
finally
{ }
return result;
}
private static string GetSetting(string Key, string configFilePath)
{
string result = null;
try
{
XmlDocument appSettingsDoc = new XmlDocument();
appSettingsDoc.Load(configFilePath);
XmlNode node = appSettingsDoc.SelectSingleNode("//appSettings");
XmlElement value = (XmlElement)node.SelectSingleNode(string.Format("//add[#key='" + Key + "']"));
result = (value.GetAttribute("value").ToString());
}
finally
{ }
return result;
}
private static SecureString ToSecureString(string input)
{
SecureString secure = new SecureString();
foreach (char c in input)
{
secure.AppendChar(c);
}
secure.MakeReadOnly();
return secure;
}
private static string ToInsecureString(SecureString input)
{
string returnValue = string.Empty;
IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
try
{
returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
}
finally
{
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
}
return returnValue;
}
private static string EncryptString(System.Security.SecureString input)
{
byte[] encryptedData = System.Security.Cryptography.ProtectedData.Protect(
System.Text.Encoding.Unicode.GetBytes(ToInsecureString(input)), entropy, System.Security.Cryptography.DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedData);
}
private static SecureString DecryptString(string encryptedData)
{
try
{
byte[] decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
Convert.FromBase64String(encryptedData),
entropy,
System.Security.Cryptography.DataProtectionScope.CurrentUser);
return ToSecureString(System.Text.Encoding.Unicode.GetString(decryptedData));
}
catch
{
return new SecureString();
}
}
#endregion
}
}
Update: Action start 14:31:36: Encryption.
MSI (c) (84:40) [14:31:36:525]: Invoking remote custom action. DLL: C:\Users\<username>\AppData\Local\Temp\MSIE259.tmp, Entrypoint: m1
InstallShield: Attempting to load through CLR 4 APIs...
InstallShield: Getting meta host...
InstallShield: Enumerating available runtimes...
InstallShield: Highest available runtime: v4.0.30319
InstallShield: Trying to use highest runtime...
InstallShield: Using highest version runtime...
InstallShield: Loading assembly Security.Encryption from resource 4097
InstallShield: Calling method with parameters [(System.String)C:\Program Files (x86)\<Installdir>\<configfilename>.config, (System.String)VWFPassword, (System.String)]
InstallShield: Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Program Files (x86)\<Installdir>\<configfilename>.config'.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)
at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)
at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
at System.Xml.XmlTextReaderImpl.OpenUrlDelegate(Object xmlResolver)
at System.Threading.CompressedStack.runTryCode(Object userData)
at
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.CompressedStack.Run(CompressedStack compressedStack, ContextCallback callback, Object state)
at System.Xml.XmlTextReaderImpl.OpenUrl()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.Load(String filename)
at Security.Encryption.EncrptionHelper.SetSetting(String appSettingKey, String appsettingValue, String configFilePathName)
at Security.Encryption.EncrptionHelper.SetValue(String configFilePathName, String appSettingKey, String appSettingValue)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at InstallShield.ClrHelper.CustomActionHelper.CallMethod(EntryPointInfo info)
at InstallShield.ClrHelper.CustomActionHelper.RunAction(UInt32 installHandle, Int32 entryNumber, Int64 instanceHandle)
InstallShield: Managed code threw an unhandled exception.
This is the error I receive after doing all that is mentioned in the screenshots below and doing some R&D. The directory mentioned "C:\Program Files (x86)\\.config" exists when the encryption custiom action is being called but it throws an exception.
Yes, it can be done with following steps:
1- write your required functionality in c# installer class (make sure your are using installer class)
2- Compile and add your dll into installshield (recomended create a separate component for this dll)
3- Select component view -> select above component and go to .Net settings section, set the ".Net Installer class" to true. Set the ".net installer class parameters"
Parameters are passed as key/value pair e.g
/targetDirectory="[INSTALLDIR]\"
All steps are same, just added screenshots.
Create a dll with an installer class and your encrypt/decrypt class.
Add dll and config file to component(above mentioned), if config file is already added to some other component then its fine. no need to add again.
I have added and retrieved INSTALLDIR variable as argument which is predefined. if you want to receive some input from user (from some custom textboxes) then you will need to define your own variables to store and pass values as arguments.
Creating dll with installer class and your requred logic for other task
Creating component and adding files
Mark the dll as installer class and pass arguments
Here goes installer class:
using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;
using System.Configuration.Install;
using System.Collections.Generic;
namespace EncryptionDecryption
{
[RunInstaller(true)]
public class InstallerClassDemo : Installer
{
private string installationDirectory=string.Empty;
private string testString=string.Empty ;
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
try
{
//For testing purpose only.. work only in debug mode when pdb files are deployed as well.
//Debugger.Break();
installationDirectory = Context.Parameters["INSTALLDIR"];
//I believe, the config file must be located in the installation directory if so, then use the following way to compute path
string configFilePath = Path.Combine(installationDirectory, "myConfigFile.config");
EncrptionHelper.SetValue(configFilePath, "testKey", "testValue");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
protected override void OnCommitted(System.Collections.IDictionary savedState)
{
base.OnCommitted(savedState);
}
public override void Uninstall(System.Collections.IDictionary savedState)
{
base.Uninstall(savedState);
}
}
}
I think installshield cannot (or need extra work) for read your assemblies, but you can run simple console application which consume your assemblies from installscript and passing parameter from installshield.
Create simple console application
Include console application on Support Files
Copy to installation folder or assemblies location, so console application can access your assemblies
Launch from installscript using launchappandwait
If consoleapp.exe not use anymore, just delete it.
I am trying to run a simple application that uses drool.net. Whenever I execute, the application crashed at builder.AddPackageFromDrl("DroolsApp.Rules.drl", stream); The Error stated that NullReferenceException was unhandled and Object reference not set an instance of an object. I tried to change drl file but the error was still present. Am I missing anything? Also is there any site that provides a detailed tutorial for using drools.net and do I need any specific program to create and edit drl files as I am using a simple notepad.
Thanks in Advance
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using org.drools.dotnet.compiler;
using org.drools.dotnet.rule;
using org.drools.dotnet;
using System.IO;
using System.Reflection;
namespace DroolsApp
{
class Program
{
static void Main(string[] args)
{
PackageBuilder builder = new PackageBuilder();
Stream stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("DroolsApp.Rules.drl");
builder.AddPackageFromDrl("DroolsApp.Rules.drl", stream);
Package pkg = builder.GetPackage();
RuleBase ruleBase = RuleBaseFactory.NewRuleBase();
ruleBase.AddPackage(pkg);
executeRules(ruleBase, 5);
executeRules(ruleBase, 6);
executeRules(ruleBase, 7);
}
public static void executeRules(RuleBase ruleBase, int amount)
{
WorkingMemory workingMemory = ruleBase.NewWorkingMemory();
Quest quest = new Quest();
quest.Value = amount;
workingMemory.assertObject(quest);
workingMemory.fireAllRules();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DroolsApp
{
class Quest
{
public int Value { set; get; }
}
}
DRL File:
package DroolsApp
rule "NumberFive"
when
quest : Quest( Value == 5 )
then
Console.WriteLine("FIVE");
end
rule "NumberSix"
when
quest : Quest( Value == 6 )
then
Console.WriteLine("SIX");
end
Stack Trace:
System.NullReferenceException was unhandled
Message=Object reference not set to an instance of an object.
Source=drools.dotnet
StackTrace:
at org.drools.dotnet.semantics.DotnetClassTypeResolver.resolveType(String className)
at org.drools.semantics.java.RuleBuilder.build(ColumnDescr columnDescr)
at org.drools.semantics.java.RuleBuilder.build(RuleDescr ruleDescr)
at org.drools.semantics.java.RuleBuilder.build(Package pkg, RuleDescr ruleDescr)
at org.drools.compiler.PackageBuilder.addRule(RuleDescr ruleDescr)
at org.drools.compiler.PackageBuilder.addPackage(PackageDescr packageDescr)
at org.drools.compiler.PackageBuilder.addPackageFromDrl(String fileName, Reader reader)
at org.drools.dotnet.compiler.PackageBuilder.AddPackageFromDrl(String fileName, Stream drlStream)
at MinimalDroolsForm.Program.Main(String[] args) in C:\Users\Carl\Desktop\DroolsApp\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
It's for sure an error in drl file. Try to remove all rules and imports, compile them, and then add single line and repeat (it must validate though). Drools.net reacts for compilation errors with NullReferenceException or an error with loading CompiledRules0.dll (because it wasn't generated). It is also a good thing to add a Pre-build Build Event deleting the previously generated CompiledRules0.dll (when Drools.net fails to generate the file it uses the previous one). Here's the code:
cd $(TargetDir)
del CompiledRules0.*
Two hints:
1) when calling GetManifestResourceStream method, be sure to pass namespace and filename as parameter.
2) In visual studio (if you are using it), rule file properites, set build action to embedded resource.
I created a standard XsltContext class and call it as follows:
XPathCustomContext context = new XPathCustomContext(new NameTable());
context.AddNamespace("windward", XPathCustomContext.Namespace);
XsltArgumentList varList = new XsltArgumentList();
varList.AddParam("stat-index", "", 0);
context.ArgList = varList;
XmlDocument doc = new XmlDocument();
doc.Load("c:\\test\\order.xml");
object xx = doc.CreateNavigator().Evaluate("/order[1]/customer[1]/num[#negone = $stat-index]", context);
When running under .net 4.0 it works fine. But under .NET 3.5 (which we have to use at present) I get:
System.Xml.XPath.XPathException was unhandled
Message=XsltContext is needed for this query because of an unknown function.
Source=System.Xml
StackTrace:
at MS.Internal.Xml.XPath.CompiledXpathExpr.UndefinedXsltContext.ResolveVariable(String prefix, String name)
at MS.Internal.Xml.XPath.VariableQuery.SetXsltContext(XsltContext context)
at MS.Internal.Xml.XPath.LogicalExpr.SetXsltContext(XsltContext context)
at MS.Internal.Xml.XPath.FilterQuery.SetXsltContext(XsltContext input)
at MS.Internal.Xml.XPath.CompiledXpathExpr.SetContext(XmlNamespaceManager nsManager)
at System.Xml.XPath.XPathExpression.Compile(String xpath, IXmlNamespaceResolver nsResolver)
at System.Xml.XPath.XPathNavigator.Evaluate(String xpath, IXmlNamespaceResolver resolver)
at CustomXpathFunctions.Program.Main(String[] args) in c:\src\CustomXpathFunctions\Program.cs:line 62
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Any idea why?
Sample code at http://www.windwardreports.com/temp/CustomXPathFunctionsBug.zip
thanks - dave
Figured out a way to do this. Use an XPathExpression like:
XPathNavigator nav = doc.CreateNavigator();
XPathExpression exp = nav.Compile("/order[1]/customer[1]/num[#negone = $stat]");
exp.SetContext(ctx);
object zzz = nav.Evaluate(exp);
As to why - my guess is Evaluate(string, context) uses it for namespaces only in .NET 3.5 while XPathExpression uses it for everything. The critical point though is this works.
ps - Please upvote the snot out of this answer - this was really hard to figure out.