Google Scripts, calling isRequired and setRequired on multipleChoiceItem fails - c#

I'm working on a piece of C#-code that maintains a questionnaire on Forms and keeps it in sync with a local database, e.g. when users use the program they simultaneously change data on Forms and in the database.
Since there is no Forms-API I'm using Google Scripts with a couple of helper methods as an inbetween to perform the changes on Forms.
One of the options of the program is to change existing questions, and specifically whether a question is required to be answered. I use the following code:
var questionItem = listOfItems[startOfSection + 1];
var currQues = questionItem.getTitle();
if(currQues !== questionString) {
Logger.log('Changed questionString from ' + currQues + ' to ' + questionString);
questionItem.setTitle(questionString);
}
var currReq = questionItem.isRequired();
if(currReq !== isQuestionRequired) {
questionItem.setRequired(isQuestionRequired);
}
When checking for the type of variable questionItem by calling the getType()-method, it tells me it's a multipleChoiceItem, which has a method called isRequired to read the current bool, and setRequired to set the bool. However, calling both isRequired and setRequired fail, the error message being
[Cannot find function isRequired in object Item.]
and the error type is
[TypeError]
Logger shows my questionItem var is a MultipleChoiceItem, so why does my code fail? And why does Scripts return a value to my C#-code saying the method was called on a generic "Item"?
Another method that sets new questions also calls setRequired after creating a MultipleChoiceItem and that one works without a problem.
FYI, startOfSection, questionString and isQuestionRequired are parameters given to the method during the request using the ScriptsService of the C# API.

setRequired requires a Boolean as parameter. The problem is that isQuestionRequired is not a Boolean.
If isQuestionRequired is a string, which value is 'true', you could replace
questionItem.setRequired(isQuestionRequired)
by
questionItem.setRequired(isQuestionRequired === 'true');

var questionItem = listOfItems[startOfSection + 1];
The above line of code tell us that questionItem gets its values from an array. It's very likely that problem is on how the array members were created.
As you already found that the error occurred on an object of "generic item" type, one solution is to use asMultipleChoiceItem() to make to conversition to the expected type.
Change
questionItem.setRequired(isQuestionRequired)
to
questionItem.asMultipleChoiceItem().setRequired(isQuestionRequired)

Related

How to find a type by FQN in a solution?

I am writing a Rider/ReSharper nav-from-here plugin which is supposed to determine a target type based on a symbol I am standing on using some simple rules, and finally, navigate to it.
The first part is okay, I have managed to form the FQN needed, but I am struggling with the navigation. I found this StackOverflow post, and thought I might try this approach. So I have been trying to use TypeFactory.CreateTypeByCLRName for like two hours to create an IDeclaredType instance to be able to get the IDeclaredElement using GetTypeElement() and eventually get its declarations. But the API seems to have changed and no matter what I do I cannot get my code to work.
Here is what I've got so far:
// does not work with Modules.GetModules(), either
foreach (var psiModule in solution.GetPsiServices().Modules.GetSourceModules())
{
var type = TypeFactory.CreateTypeByCLRName("MyNamespace.MyClassName", psiModule);
var typeElement = type.GetTypeElement();
if (typeElement != null)
{
MessageBox.ShowInfo(psiModule.Name); // to make sure sth is happening
break;
}
}
The weird part is, I actually see a message box - but only when the tab with MyClassName.cs is active. When it is in focus, everything is fine. When it's not or the file is closed, the class does not get resolved, type.IsResolved is false.
What am I doing wrong?
To do this, you should have a IPsiModule instance from the context where you plan to use the type you're looking for. You can get it from some syntax node you're working with via .GetPsiModule() method or via many other ways (like dataContext.GetData(PsiDataConstants.SOURCE_FILE)?.GetPsiModule().
void FindTypes(string fullTypeName, IPsiModule psiModule)
{
// access the symbol cache where all the solution types are stored
var symbolCache = psiModule.GetPsiServices().Symbols;
// get a view on that cache from specific IPsiModule, include all referenced assemblies
var symbolScope = symbolCache.GetSymbolScope(psiModule, withReferences: true, caseSensitive: true);
// or use this to search through all of the solution types
// var symbolScope = symbolCache.GetSymbolScope(LibrarySymbolScope.FULL, caseSensitive: true);
// request all the type symbols with the specified full type name
foreach (var typeElement in symbolScope.GetTypeElementsByCLRName(fullTypeName))
{
// ...
}
}

Conversion of vbs to C#, unable to get ScriptingEngine

I have a VBScript which automates a little step of a SAPGUI Application.
The point is, it is needed to be converted to a dll due to internal reasons. So I created a .Net Class Library and added the Microsoft.VisualBasic.dll as assembly reference. Now I am able to get the application object, but I'm unable to execute the following methods on the object itself.
I tried through getting the type of the application and then calling getMethod() to access the function, but this didn't work out.
object application = SapGuiAuto.GetType().GetMethod("GetScriptingengine");
And I tried accessing the function through the Microsoft.VisualBasic.Interaction.Methods but these do not provide the function needed.
Here my vbs:
Set SapGuiAuto = GetObject("SAPGUI")
Set application = SapGuiAuto.GetScriptingEngine
If Not IsObject(connection) Then
Set connection = application.Children(0)
End If
If Not IsObject(session) Then
Set session = connection.Children(0)
End If
If IsObject(WScript) Then
WScript.ConnectObject session, "on"
WScript.ConnectObject application, "on"
End If
session.findById("wnd[0]").maximize
session.findById("wnd[0]/usr/cntlIMAGE_CONTAINER/shellcont/shell/shellcont[0]/shell").selectedNode = "0000000003"
session.findById("wnd[0]/usr/cntlIMAGE_CONTAINER/shellcont/shell/shellcont[0]/shell").doubleClickNode "0000000003"
session.findById("wnd[0]/usr/cntlIMAGE_CONTAINER/shellcont/shell/shellcont[0]/shell").selectedNode = "0000000004"
session.findById("wnd[0]/usr/cntlIMAGE_CONTAINER/shellcont/shell/shellcont[0]/shell").nodeContextMenu "0000000004"
session.findById("wnd[0]/usr/cntlIMAGE_CONTAINER/shellcont/shell/shellcont[0]/shell").selectContextMenuItem "XXEXEC"
session.findById("wnd[0]/usr/cntlSINWP_CONTAINER/shellcont/shell/shellcont[0]/shell").selectedNode = " 2"
session.findById("wnd[0]/usr/cntlSINWP_CONTAINER/shellcont/shell/shellcont[0]/shell").selectedNode = " 3"
session.findById("wnd[0]/usr/cntlSINWP_CONTAINER/shellcont/shell/shellcont[1]/shell/shellcont[0]/shell").pressToolbarButton "CREA_RAW"
Sadly my C# Script is quite small, since it's the first thing I'm getting stuck on:
public static void RunScriptParameterless()
{
object SapGuiAuto = Interaction.GetObject("SAPGUI", "");
MethodInfo application = SapGuiAuto.GetType().GetMethod("GetScriptingengine");
object session = application.Invoke(SapGuiAuto, null);
}
I just get a NullPointerException on the application declaration line.
Actually I want an object just like in the VBS which is a connection on which I can operate on.

"Object reference not set to an instance of an object" exception when assigning EF property to variable

I'm getting an "Object reference not set to an instance of an object" exception when I'm trying to assign one of the property of my EF object model to a variable but can't figure out why as the EF object definitely contains data and is accessible in the Immediate Window.
I call the following code to get data from a specific organization:
var organizationModelFromDb = this.DbContext.Organizations.
SingleOrDefault(o => o.OrganizationId ==
organizationEditViewModel.Organization.OrganizationId);
This definitely returns data as I can see data displayed when expanding the tooltip when hovering my mouse over the organizationModelFromDb object. I can also access the data when I type:
organizationModelFromDb.MembershipType
in the Immediate Window but when I try to assign this property from my object model as such:
var membershipType = organizationModelFromDb.MembershipType;
I get the mentioned exception.
Everything within this Controller's method is working as expected but I was in the process of introducing new functionality but I'm stuck with this problem.
Any idea what may be happening. I'm pretty sure I'm assigning EF data to variables using the same technique all over the place in my project but for whatever reason it just won't work in this method.
What am I missing?
UPDATE-1:
This is not a duplicate question. The referenced article deal with the fact that object may actually be null and how best handle each scenario but as explained my object is not actually null. Data is being returned and it is available via the immediate window and the tooltip.
Update-2
This is the data I get when I'm calling "organizationModelFromDb" from the immediate window:
{System.Data.Entity.DynamicProxies.
OrganizationModel_2AEF19E09C5699B8E172F0AA73D6DB
71945EF111ADF7AE5EAEB3AD073A15D5A3}
AdditionalDetails:
{System.Data.Entity.DynamicProxies.OrganizationAddition_
05739F8DE2F5D549B3A7FC852AC32ED9C002953ED41AAA7751B12289E23D8A6C}
AutoImport: false
Members: Count = 1
MembershipType: Full
OrganizationId: "4be433d5-48a9-4891-a008-c70fe4cfoie3"
OrganizationName: "My Company"
StatusType: Approved
Website: ""
_entityWrapper: {System.Data.Entity.Core.Objects.Internal.EntityWrapperWithoutRelationships<System.Data.Entity.DynamicProxies.OrganizationModel_2AEF19E09C5699B8E172F0AA73D6DB71945EF111ADF7AE5EAEB3AD073A15D5A3>}
As you can see, there is data in the object.
But as mentioned, when I call this line of code:
var membershipType = organizationModelFromDb.MembershipType;
in my code, I get the exception with the following StackTrace:
"System.NullReferenceException: Object reference not set to an instance of an object.
at Mywebsite.Controllers.OrganizationsController.d__8.MoveNext() in C:\Work\MyWebsite\Controllers\OrganizationsController.cs:line 349"
Hope this helps resolving my problem.
Update-3
I've removed the code originally provided in this update to keep things tidy rather than providing yet another update but the code below is the full code contained in my controller but note that I've removed unnecessary code for readability sake:
var organizationModelFromDb = await this.DbContext.Organizations
.FirstOrDefaultAsync<OrganizationModel>(o => o.OrganizationId ==
organizationEditViewModel.Organization.OrganizationId);
if (ReferenceEquals(organizationModelFromDb, null))
return HttpNotFound();
organizationModelFromDb.StatusType = StatusType.Approved;
var memberModelsFromDb =
this.DbContext.Members.Where(
m => m.OrganizationId ==
organizationEditViewModel.Organization.OrganizationId).ToList();
if (memberModelsFromDb.Count > 0)
{
foreach (var memberModel in memberModelsFromDb.ToList())
{
var user = new ApplicationUser
{
UserName = memberModel.Email,
Email = memberModel.Email,
UserType = UserType.IsMember
};
var password = RandomPassword.Generate();
var result = await this.UserManager.CreateAsync(user, password);
if (result.Succeeded)
{
await this.UserManager.AddToRoleAsync(user.Id, JoiffRoles.IsMember);
try
{
var membershipType = organizationModelFromDb.MembershipType;
}
catch (Exception e)
{
Console.WriteLine(e);
}
string code = await this.UserManager.
GenerateEmailConfirmationTokenAsync(user.Id);
string codeHtmlVersion = HttpUtility.UrlEncode(code);
new Thread(async () =>
{
await CustomEmailService.
SendConfirm(this, Request, user, codeHtmlVersion);
}).Start();
}
}
}
Now as you can see, there's nothing special about this code. I'm checking if an organization exists, then I'm getting all the members for that organization and then I'm looping through each member and creating a user and adding roles to the database. Once created successfully, it sends an email to the newly created user with credential information.
Now the weird part, the exception "Object reference not set to an instance of an object" occurs with the above code but somehow, it doesn't occur if I comment either section of code:
1) Remove everything above the try/catch but leave the email section below the try catch:
var password = RandomPassword.Generate();
var result = await this.UserManager.CreateAsync(user, password);
if (result.Succeeded)
{
await this.UserManager.AddToRoleAsync(user.Id, JoiffRoles.IsMember);
…
}
2) Remove the email section
new Thread(async () =>
{
await CustomEmailService.SendConfirm(this,
Request, user, codeHtmlVersion);
}).Start();
I know this sounds ridiculous, I've gone through it over and over again and if I leave the code as is, I get this error when trying to set the variable to the OrganizationFromDb.MembershipType. If I remove either of the section mentioned above, everything works as expected.
As #CamiloTerevinto mentioned, I do believe it is related to something that hasn't been fully fetched and is only partially built but how are either section affecting this?
Any suggestions?
I haven't got to the bottom as to why this is happening nor why does it work when removing snippets of codes as mentioned in my updates but I'm pretty sure it is indeed related to what #CamiloTerevinto previously mentioned regarding the EF entity being only partially built/queried.
I can only assume that displaying data in the Immediate window and/or via the tooltip behaves differently than using it at run-time when assigned to a variable.
Anyway, rather than trying to fixed and/or figure out why removing these snippets of codes did the trick, I thought I'd try a different approach.
Since my organization details were only required to be pulled once there was no need for it to be within the members loop, so
I decided to assign the MembershipType variable outside the Members
loop
and this appeared to have done the trick.
I wonder if it is related to EF's lazy loading or something similar where it is trying to fetch the organization's EF entity details when requested within a loop that's also fetching details about another object. I'm not sure to be honest.
Would love someone to highlight and explain the actual reason.
I hope this help.

ActiveDirectory error 0x8000500c when traversing properties

I got the following snippet (SomeName/SomeDomain contains real values in my code)
var entry = new DirectoryEntry("LDAP://CN=SomeName,OU=All Groups,dc=SomeDomain,dc=com");
foreach (object property in entry.Properties)
{
Console.WriteLine(property);
}
It prints OK for the first 21 properties, but then fail with:
COMException {"Unknown error (0x8000500c)"}
at System.DirectoryServices.PropertyValueCollection.PopulateList()
at System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry, String propertyName)
at System.DirectoryServices.PropertyCollection.PropertyEnumerator.get_Entry()
at System.DirectoryServices.PropertyCollection.PropertyEnumerator.get_Current()
at ActiveDirectory.Tests.IntegrationTests.ObjectFactoryTests.TestMethod1() in MyTests.cs:line 22
Why? How can I prevent it?
Update
It's a custom attribute that fails.
I've tried to use entry.RefreshCache() and entry.RefreshCache(new[]{"theAttributeName"}) before enumerating the properties (which didn't help).
Update2
entry.InvokeGet("theAttributeName") works (and without RefreshCache).
Can someone explain why?
Update3
It works if I supply the FQDN to the item: LDAP://srv00014.ssab.com/CN=SomeName,xxxx
Bounty
I'm looking for an answer which addresses the following:
Why entry.Properties["customAttributeName"] fails with the mentioned exception
Why entry.InvokeGet("customAttributeName") works
The cause of the exception
How to get both working
If one wants to access a custom attribute from a machine that is not
part of the domain where the custom attribute resides (the credentials
of the logged in user don't matter) one needs to pass the fully
qualified name of the object is trying to access otherwise the schema
cache on the client machine is not properly refreshed, nevermind all
the schema.refresh() calls you make
Found here. This sounds like your problem, given the updates made to the question.
Using the Err.exe tool here
http://www.microsoft.com/download/en/details.aspx?id=985
It spits out:
for hex 0x8000500c / decimal -2147463156 :
E_ADS_CANT_CONVERT_DATATYPE adserr.h
The directory datatype cannot be converted to/from a native
DS datatype
1 matches found for "0x8000500c"
Googled "The directory datatype cannot be converted to/from a native" and found this KB:
http://support.microsoft.com/kb/907462
I have the same failure. I´m read and saw a lot of questions about the error 0x8000500c by listing attribute from a DirectoryEntry.
I could see, with the Process Monitor (Sysinternals), that my process has read a schema file. This schema file is saved under
C:\Users\xxxx\AppData\Local\Microsoft\Windows\SchCache\xyz.sch.
Remove this file and the program works fine :)
I just encountered the issue and mine was with a web application.
I had this bit of code which pulls the user out of windows authentication in IIS and pulls their info from AD.
using (var context = new PrincipalContext(ContextType.Domain))
{
var name = UserPrincipal.Current.DisplayName;
var principal = UserPrincipal.FindByIdentity(context, this.user.Identity.Name);
if (principal != null)
{
this.fullName = principal.GivenName + " " + principal.Surname;
}
else
{
this.fullName = string.Empty;
}
}
This worked fine in my tests, but when I published the website it would come up with this error on FindByIdentity call.
I fixed the issue by using correct user for the app-pool of the website. As soon as I fixed that, this started working.
I had the same problem with a custom attribute of a weird data type. I had a utility program that would extract the value, but some more structured code in a service that would not.
The utility was working directly with a SearchResult object, while the service was using a DirectoryEntry.
It distilled out to this.
SearchResult result;
result.Properties[customProp]; // might work for you
result.Properties[customProp][0]; // works for me. see below
using (DirectoryEntry entry = result.GetDirectoryEntry())
{
entry.Properties[customProp]; // fails
entry.InvokeGet(customProp); // fails as well for the weird data
}
My gut feel is that the SearchResult is a little less of an enforcer and returns back whatever it has.
When this is converted to a DirectoryEntry, this code munges the weird data type so that even InvokeGet fails.
My actual extraction code with the extra [0] looks like:
byte[] bytes = (byte[])((result.Properties[customProp][0]));
String customValue = System.Text.Encoding.UTF8.GetString(bytes);
I picked up the second line from another posting on the site.

Object reference not set to an instance of an object

I usually get this error and (always) don't know how to solve it.
This time I got it also, it seems that I'm not understanding a concept or missing something
Here's the code
// create a new twitteroo core with provided username/password
TwitterooCore core = new TwitterooCore(username, password);
// request friends timeline from twitter
Users users = core.GetTimeline(Timeline.Friends); // error here
Please some help and also some explanations of what's happening
Thanks
This error is a pain, it basically means some vairable you're accessing is still Null.
In this instance, where do you initialise Timeline? Should your code be something like:
Users users = core.GetTimeline().Friends;
OK, I've been looking at the twiteroo documentation, which is a bit sparse, and I think you definitely need to instantiate an instance of Timeline to pass into GetTimeline, (which returns a collections of Users, not very well named IMHO). What I can't figure out is how to initiate an instance of Timeline.
OK, it's not Timeline that's null, (that's an Enum!) so as bthb says, it can only be the core, perhaps the username or password are wrong, or it can't connect to twitter?
I found the problem finally
It was because of my Firewall seems to be blocking connections to Visual Studio.
Now it works with no changes at all :)
Thanks for all your support
It could be core, username, password, or Timeline.Friends, impossible to know which by the info you have given us.
If I were you I'd put a breakpoint on the line that errors, then stick a watch on Timeline.Friends and check its not null, if its not then put a watch on core.GetTimeline(Timeline.Friends) and see if thats returning null.
It should give you a nudge in the right direction, you'll probably have to read the documentation for the twitter API your using to find out why either of these is returning null.
How about checking your code like:
Users users = null;
if (Timeline != null)
{
TwitterooCore core = new TwitterooCore(username, password);
if (core != null)
{
var friends = Timeline.Friends
if (friends != null)
users = core.GetTimeline(Timeline.Friends);
}
}
If this runs without exceptions one of the objects was probably null.
There are two specific phrases in the error message, object reference and instance of an object. These concepts are very basic when dealing with OOP languages.
First, an object reference can be thought of a variable in a function or class. This term may also refer to function parameters that expect a specific reference to an object. Initially the value of a variable is NULL until it is set to a value using the '=' operator. Frequently you will have a variable declaration and the '=' operation in the same statement.
The term instance of an object refers to an object that has been created using the syntax new. When you call new to initialize an object, an unused memory location is allocated to store a copy of the object until the program ends, or the object goes out of scope and is freed by the garbage collector. At creation time the object properties are defined by the constructor method called to create the object.
Consider this code:
Integer my_int;
my_int = new Integer(5);
In this example, 'my_int' is the object reference to an Integer object instance being created.
If you try to access 'my_int', before assigning it a reference to an Integer instance, then you would have the error, "an object reference (my_int) not set to an instance of an object (Integer)".
If you decompile the dll you will see that GetTimeline(Enum) takes in a Enumeration argument.
The Constructor call will be fine:
TwitterooCore core = new TwitterooCore(username, password);
Source:
public TwitterooCore(string username, string password)
{
this._username = username;
this._password = password;
}
GetTimeline is were the connection is attempted.
public Users GetTimeline(Timeline timeline)
{
WebClient client = new WebClient();
XmlDocument document = new XmlDocument();
string xml = string.Empty;
byte[] buffer = null;
client.set_Credentials(this.GetCredentials());
buffer = client.DownloadData(this.GetTimelineUrl(timeline));
xml = Encoding.UTF8.GetString(buffer);
document.LoadXml(xml);
return this.DecodeStatusXml(document);
}
May be Timeline.Friends is null and may be Timeline is null. I suggest you look at the stack trace of exception and into documentation of your twitter framework.

Categories