SMS_Application WMI class's equivalent table in SCCM database - wmi

I'm having an AppModel application in my System Center Configuration Manager(SCCM) console. Please see below screenshot of the properties window of the SCCM application:
I need to know the value of 'Allow this application to be installed from the Install Application task sequence.....' checkbox. It is highlighted in yellow.
I tried to get it through wbemtest tool using below details:
Namespace: root\sms\site_[siteCode] e.g. root\sms\site_lab
Query: select * from SMS_Application
I hope I've got the correct Windows Management Instrumentation(WMI) class for AppModel CM applications.
But the output in wbemtest tool doesn't give any field in the result output which can reflect the current condition of checkbox:
Instance of SMS_Application
{
ApplicabilityCondition = "";
CategoryInstance_UniqueIDs = {};
CI_ID = 16777532;
CI_UniqueID = "ScopeId_6AFF9AA6-E784-4BB8-8DCF-816FCF7A7C09/Application_8e417c4c-da5d-4f1c-91af-ed63d63f9a62/3";
CIType_ID = 10;
CIVersion = 3;
CreatedBy = "NTL\\administrator";
DateCreated = "20190724122559.000000+000";
DateLastModified = "20200422051705.000000+000";
EULAAccepted = 2;
EULAExists = FALSE;
ExecutionContext = 0;
Featured = 0;
HasContent = TRUE;
IsBundle = FALSE;
IsDeployable = TRUE;
IsDeployed = FALSE;
IsEnabled = TRUE;
IsExpired = FALSE;
IsHidden = FALSE;
IsLatest = TRUE;
IsQuarantined = FALSE;
IsSuperseded = FALSE;
IsSuperseding = FALSE;
IsUserDefined = TRUE;
IsVersionCompatible = TRUE;
LastModifiedBy = "NTL\\estateadministrator";
LocalizedCategoryInstanceNames = {};
LocalizedDescription = "";
LocalizedDisplayName = "7-Zip 19.00 (x64 edition)";
LocalizedInformativeURL = "";
LocalizedPropertyLocaleID = 65535;
LogonRequirement = 0;
Manufacturer = "";
ModelID = 16777500;
ModelName = "ScopeId_6AFF9AA6-E784-4BB8-8DCF-816FCF7A7C09/Application_8e417c4c-da5d-4f1c-91af-ed63d63f9a62";
NumberOfDependentDTs = 0;
NumberOfDependentTS = 0;
NumberOfDeployments = 0;
NumberOfDeploymentTypes = 1;
NumberOfDevicesWithApp = 0;
NumberOfDevicesWithFailure = 0;
NumberOfSettings = 0;
NumberOfUsersWithApp = 0;
NumberOfUsersWithFailure = 0;
NumberOfUsersWithRequest = 0;
NumberOfVirtualEnvironments = 0;
PermittedUses = 0;
PlatformCategoryInstance_UniqueIDs = {};
PlatformType = 1;
SDMPackageVersion = 3;
SecuredScopeNames = {"Default"};
SedoObjectVersion = "9B99BA03-D0FA-417C-8BFF-6095B88AD179";
SoftwareVersion = "";
SourceCIVersion = 0;
SourceModelName = "";
SourceSite = "LAB";
SummarizationTime = "20200422125059.533000+***";
};
Is it possible that WMI class is not exposing all the columns of the database backed by this WMI class. Hence, I'm looking for the SQL DB table of SCCM DB so that I can query it directly at DB level. Can anyone help me in this regard?
Update: I also need the table which I can update to set/reset the Boolean field corresponding to the checkbox shown on UI.

The information is stored inside an XML element called SDMPackageXML in WMI. The corresponding table the console uses is fn_listApplicationCIs_List(1031) (it is also present in fn_listApplicationCIs(1031) I am at the moment not sure what the exact difference here is) where it is called SDMPackageDigest. The element is simply called "AutoInstall" and it is only present if set to true. To query it with WQL is impossible, however in a script it could be done by not using a query but a Get() on the SMS_Application Object (because SDMPackageXML is a lazy property) and then parsing the XML.
In SQL however it is possible to directly query the XML Part of a column like this:
SELECT
DisplayName,
CI_UniqueID
FROM
fn_ListApplicationCIs_List(1031) app
WHERE
app.isLatest = 1
AND
app.SDMPackageDigest.value('declare namespace p1="http://schemas.microsoft.com/SystemCenterConfigurationManager/2009/AppMgmtDigest";(p1:AppMgmtDigest/p1:Application/p1:AutoInstall)[1]', 'nvarchar(max)') = 'true'
(the isLatest is necessary to discard older versions of the application).
It is also possible to include the value in the select with that syntax, just keep in mind that it will be true for all Applications that are enabled for TS deployment and NULL for the others.
Now as for how to update. The SCCM DB should never be written to. I don't know if it would even be possible to achieve a change this way (it could be that WMI is always leading and would overwrite it), and as this is all undocumented it could be that changes have to be done at specific places or multiple places at the same time. If this has to be updated you have to resort to scripts, that can work with the lazy WMI properties. However I do not know of a way that is not dependent on SCCM specific dlls (doesn't mean there is none but I do not know how to work with XML well enough for this) so you will need Microsoft.ConfigurationManagement.ApplicationManagement.dll from the bin directory of a ConfigMgr Console Installation dir. (I wrote the code so that it would automatically find it on a computer where the Console is installed). Then you can do it like this (can of course also be wrapped in a for):
[System.Reflection.Assembly]::LoadFrom((Join-Path (Get-Item $env:SMS_ADMIN_UI_PATH).Parent.FullName "Microsoft.ConfigurationManagement.ApplicationManagement.dll"))
$app = gwmi -computer <siteserver> -namespace root\sms\site_<sitecode> -class sms_application -filter "LocalizedDisplayName='<appname>' and isLatest = 'true'"
$app.Get()
$sdmPackageXML = [Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::DeserializeFromString($app.SDMPackageXML, $true)
$sdmPackageXML.AutoInstall = $true
$app.SDMPackageXML = [Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::SerializeToString($sdmPackageXML, $true)
$app.Put()
The nice thing is that this deserialization always presents us with an AutoInstall property even if it is not present in the xml because it was written for sccm so we can just set it true/false as we want.
The reason we need the .dll is the serialization. Deserialisation can be done with a simple cast to [xml] as well but I am not sure how it could be serialized again. If this can be done there is no need for external dlls. (However the xml manipulation is less easy).
If you run this code on a machine with the sccm console anyway you could also skip the wmi part and use Get-CMApllication from the sccm ps commandlets (contains SDMPackageXML as well) however while the dll can be moved to any computer, the cmdlets are only installed with the console so I wrote the sample without them.

Related

Generating a data table to iterate through in a Django Template

I have this function that uses PrettyTables to gather information about the Virtual Machines owned by a user. Right now, it only shows information and it works well. I have a new idea where I want to add a button to a new column which allows the user to reboot the virutal machine. I already know how to restart the virtual machines but what I'm struggling to figure out is the best way to create a dataset which i can iterate through and then create a HTML table. I've done similar stuff with PHP/SQL in the past and it was straight forward. I don't think I can iterate through PrettyTables so I'm wondering what is my best option? Pretty tables does a very good job of making it simple to create the table (as you can see below). I'm hoping to use another method, but also keep it very simple. Basically, making it relational and easy to iterate through. Any other suggestions are welcome. Thanks!
Here is my current code:
x = PrettyTable()
x.field_names = ["VM Name", "OS", "IP", "Power State"]
for uuid in virtual_machines:
vm = search_index.FindByUuid(None, uuid, True, False)
if vm.summary.guest.ipAddress == None:
ip = "Unavailable"
else:
ip = vm.summary.guest.ipAddress
if vm.summary.runtime.powerState == "poweredOff":
power_state = "OFF"
else:
power_state = "ON"
if vm.summary.guest.guestFullName == None:
os = "Unavailable"
else:
os = vm.summary.guest.guestFullName
x.add_row([vm.summary.config.name, os, ip, power_state])
table = x.get_html_string(attributes = {"class":"table table-striped"})
return table
Here is a sample of what it looks like and also what I plan to do with the button. http://prntscr.com/nki3ci
Figured out how to query the prettytable. It was a minor addition without having to redo it all.
html = '<table class="table"><tr><th>VM Name</th><th>OS</th><th>IP</th><th>Power
State</th></tr>'
htmlend = '</tr></table>'
body = ''
for vmm in x:
vmm.border = False
vmm.header = False
vm_name = (vmm.get_string(fields=["VM Name"]))
operating_system = (vmm.get_string(fields=["OS"]))
ip_addr = ((vmm.get_string(fields=["IP"])))
body += '<tr><td>'+ vm_name + '</td><td>' + operating_system + '</td> <td>'+ ip_addr +'</td> <td>ON</td></tr>'
html += body
html += htmlend
print(html)

How to access unwanted save file name and delete it?

I need to filter my raster image by a fixed threshold. So I use ILogicalOp functions. Whenever I use them, an output file will be saved on workspace, which is unwanted due to my large database. The saving happens exactly after rasOut[i] = RMath.LessThan(inputRas[i], cons01). How can I prevent this? Or how to get saved file name and delete it? Any comments would be Appreciated?
private IGeoDataset[] CalcColdThreshold(IGeoDataset[] inputRas)
{
IGeoDataset[] rasOut = new IGeoDataset[inputRas.Length];
IGeoDataset emptyRas=null;
ILogicalOp RMath;
RMath = new RasterMathOpsClass();
IRasterAnalysisEnvironment env;
env = (IRasterAnalysisEnvironment)RMath;
IWorkspaceFactory workspaceFactory = new RasterWorkspaceFactoryClass();
IWorkspace workspace = workspaceFactory.OpenFromFile(System.IO.Path.GetFullPath(workSpace_save.Text), 0);
env.OutWorkspace = workspace;
IRasterMakerOp Rmaker = new RasterMakerOpClass();
IGeoDataset cons01;
Threshold_value = 15000;
cons01 = Rmaker.MakeConstant(Threshold_value, false);
for (int i = 0; i < inputRas.Length; i++)
{
rasOut[i] = RMath.LessThan(inputRas[i], cons01);
}
return rasOut;
}
(disclaimer: I'm not actually a C++ programmer, just trying to provide some pointers to get you going since no one else seems to have any answers.) (converted from comment)
The IScratchWorkspaceFactory interface sounds like it will do what you want - instead of creating your workspace variable using IWorkspaceFactory.OpenFromFile, try creating a scratch workspace instead? According to the documentation it will be automatically cleaned up when your application exits.
Just remember to use a different workspace for your final output. :)

Sharepoint 2013 - Taxonomy- Microsoft.SharePoint.Taxonomy.TaxonomySession.GetTaxonomySession”

I am updating manage meta data field using C#.
Following is code to get TermId for term.
string termId = string.Empty;
try
{
TaxonomySession tSession = TaxonomySession.GetTaxonomySession(CC);
TermStore termStore = taxonomySession.GetDefaultSiteCollectionTermStore();
TermSet tset = ts.GetTermSet(termSetId); // I have proper Guid here, checked this in SharePoint 2013 server.
LabelMatchInformation lmi = new LabelMatchInformation(CC);
lmi.Lcid = 1033;
lmi.TrimUnavailable = true;
lmi.TermLabel = "xyz"; //Name of the term.
TermCollection termMatches = tset.GetTerms(lmi);
CC.Load(tSession);
CC.Load(ts);
CC.Load(tset);
CC.Load(termMatches);
CC.ExecuteQuery();
if (termMatches != null && termMatches.Count() > 0)
termId = termMatches.First().Id.ToString();
}
catch (Exception ex)
{
var d = ex.Message;
}
return termId;
}
But I am getting exception as:
“Cannot invoke method or retrieve property from null object. Object returned by the following call stack is null. \"GetDefaultSiteCollectionTermStore\r\nMicrosoft.SharePoint.Taxonomy.TaxonomySession.GetTaxonomySession”.
I have tried to load manually from Sharepoint2013, it works fine there.
Is there anything missing ?
Thanks for help..
credit to user1545314 and google
Go to the Managed Metadata service (in Service Applications in central admin).
Select Managed Metadata Service Proxy (try clicking the empty space around the text rather than the text itself), and click Properties.
Set that the application is default storage for keywords and for termsets.

How to search for Items that doesn't contain certain keywords using Sitecore Advanced Database Crawler?

I have millions of items in the database. And user can search those items based on the keyword. In the search function, I need to provide a feature that search for NOT that keyword.
For example Item A has a field called msg and the value is Sitecore is awesome and great.
In the search box, user can check the checkbox that indicates to show any item that doesn't contain the keyword. Maybe user key in is keyword, so Item A will not be displayed or retrieved by ADC.
Edit: Currently I'm using sitecore6.6, thus Search method has been deprecated. I have tried the Not keyword by using Occurrence.MustNot, but it doesn't return any result.
The Sitecore Advanced Database Crawler is an extension of the Sitecore.Search API and Sitecore.Search API is a wrapper around Lucene.
In Lucene you can user queries with NOT or - to exclude something like "Sitecore NOT awesome" or "Sitecore -awesome".
To exclude something you need at least one include term.
Not sure if it works, but give it a try.
This is untested, but you might have luck by using a MatchAllDocsQuery and supplying the keywords in the form of a Filter.
BooleanQuery booleanQuery = new BooleanQuery();
QueryParser queryParser = new QueryParser("msg", new StandardAnalyzer());
Query userQuery = queryParser.Parse("Sitecore is awesome and great");
booleanQuery.Add(userQuery, reverseQuery.Checked ? BooleanClause.Occur.MUST_NOT : BooleanClause.Occur.MUST);
MatchAllDocsQuery matchAllQuery = new MatchAllDocsQuery();
Filter filter = new QueryFilter(booleanQuery);
using (QueryRunner queryRunner = new QueryRunner("myIndex"))
{
var skinnyItems = queryRunner.RunQuery(matchAllQuery, filter, ...)
}
What I have done to NOT include the keywords associated with the result item set is this:
protected List<Item> getSearchResults(string queryToSearch, string selectedFilter, string notToSearch)
{
Database db = Sitecore.Context.Database;
var index = SearchManager.GetIndex("siteSearchIndexName");
using (SortableIndexSearchContext context = new SortableIndexSearchContext(index))
{
if (!String.IsNullOrWhiteSpace(query))
{
query.ToLower();
CombinedQuery cq = new CombinedQuery();
QueryBase qbKeyword = new FieldQuery("_orderkeywordpair", query);
QueryBase qbContent = new FieldQuery("_content", query);
QueryBase qbHtml = new FieldQuery("html", query);
if (!String.IsNullOrWhiteSpace(selectedFilter) && selectedFilter.ToLower() != "all")
{
QueryBase qbFilter = new FieldQuery("_pagetype", selectedFilter);
cq.Add(qbFilter, QueryOccurance.Must);
}
cq.Add(qbKeyword, QueryOccurance.Should);
cq.Add(qbContent, QueryOccurance.Must);
cq.Add(qbHtml, QueryOccurance.MustNot);
SearchHits hits = context.Search(cq);

Sitecore Clear Cache Programmatically

I am trying to publish programmatically in Sitecore. Publishing works fine. But doing so programmatically doesn't clear the sitecore cache. What is the best way to clear the cache programmatically?
I am trying to use the webservice that comes with the staging module. But I am getting a Bad request exception(Exception: The remote server returned an unexpected response: (400) Bad Request.). I tried to increase the service receivetimeout and sendtimeout on the client side config file but that didn't fix the problem. Any pointers would be greatly appreciated?
I am using the following code:
CacheClearService.StagingWebServiceSoapClient client = new CacheClearService.StagingWebServiceSoapClient();
CacheClearService.StagingCredentials credentials = new CacheClearService.StagingCredentials();
credentials.Username = "sitecore\adminuser";
credentials.Password = "***********";
credentials.isEncrypted = false;
bool s = client.ClearCache(true, dt, credentials);
I am using following code to do publish.
Database master = Sitecore.Configuration.Factory.GetDatabase("master");
Database web = Sitecore.Configuration.Factory.GetDatabase("web");
string userName = "default\adminuser";
Sitecore.Security.Accounts.User user = Sitecore.Security.Accounts.User.FromName(userName, true);
user.RuntimeSettings.IsAdministrator = true;
using (new Sitecore.Security.Accounts.UserSwitcher(user))
{
Sitecore.Publishing.PublishOptions options = new Sitecore.Publishing.PublishOptions(master, web,
Sitecore.Publishing.PublishMode.Full, Sitecore.Data.Managers.LanguageManager.DefaultLanguage, DateTime.Now);
options.RootItem = master.Items["/sitecore/content/"];
options.Deep = true;
options.CompareRevisions = true;
options.RepublishAll = true;
options.FromDate = DateTime.Now.AddMonths(-1);
Sitecore.Publishing.Publisher publisher = new Sitecore.Publishing.Publisher(options);
publisher.Publish();
}
In Sitecore 6, the CacheManager class has a static method that will clear all caches. The ClearAll() method is obsolete.
Sitecore.Caching.CacheManager.ClearAllCaches();
Just a quick note, in Sitecore 6.3, that is not needed anymore. Caches are being cleared automatically after a change happens on a remote server.
Also, if you are on previous releases, instead of clearing all caches, you can do partial cache clearing.
There is a free shared source component called Stager that does that.
http://trac.sitecore.net/SitecoreStager
If you need a custom solution, you can simply extract the source code from there.
I got this from Sitecore support. It clears all caches:
Sitecore.Context.Database = this.WebContext.Database;
Sitecore.Context.Database.Engines.TemplateEngine.Reset();
Sitecore.Context.ClientData.RemoveAll();
Sitecore.Caching.CacheManager.ClearAllCaches();
Sitecore.Context.Database = this.ShellContext.Database;
Sitecore.Context.Database.Engines.TemplateEngine.Reset();
Sitecore.Caching.CacheManager.ClearAllCaches();
Sitecore.Context.ClientData.RemoveAll();
Out of the box solution provided by Sitecore to clean caches (ALL of them) is utilized by the following page: http://sitecore_instance_here/sitecore/admin/cache.aspx and code behind looks like the following snippet:
foreach (var cache in Sitecore.Caching.CacheManager.GetAllCaches())
cache.Clear();
Via the SDN:
HtmlCache cache = CacheManager.GetHtmlCache(Context.Site);
if (cache != null) {
cache.Clear();
}