How to update DotNetNuke's HTML module content through code? - api

I'm working on a DNN module which needs to be able to update the HTML content of existing HTML modules. Does anyone know how to do this through code?
I've determined the content gets stored in the HtmlText table, but I'd rather not write directly to the table. Does anyone knows how to accomplish this using the DNN API?
Thanks in advance.
Here's the solution I found, with the help of mika & bdukes :
''' <summary>Add HTML contest to an existing HTML module.</summary>
Private Sub AddHTML(ByVal ModuleID As Integer, ByVal HTML As String)
Try
Dim oHTML As New DotNetNuke.Modules.Html.SqlDataProvider
'-- i'm not sure what "history" should be set for in the method below.
'-- i suspect it means "version history", which 5 seems to be the default based on what i've read.
oHTML.AddHtmlText(ModuleID, HTML, 1, 1, UserId, 5)
Catch ex As Exception
'failure
End Try
End Sub
Notes:
This routine adds HTML content to a
just-created HTML/Text module, so
checking for existing HTML content
isn't necessary.
I'm a little fuzzy about the 3rd and
6th parameters (StateID & History),
although it seems to be
working correctly. If anyone knows
more about them, I'd like to
know the correct way to set these parameters.

Version 5.2 of the HTML module (which started being distributed with DNN 5.2) and above are compiled, with a reference in the website's /bin/ directory. You can make a reference to DotNetNuke.Modules.Html.dll in your project and use the methods on HtmlTextController to make the updates (as #mika mentions). However, because of changes to the HTML module over time, you'll need to make sure that you re-check your module (and potentially update your integration) every time you update DNN.
You can take a look at our free Engage: F3 module to see how we've addressed differences in the code bases of various versions.

Use Text/HTML module. It is not distributed as a .dll, but you'll find the code in the /App_Code/HTML folder.
HtmlTextController has the methods:
- Public Sub AddHtmlText(ByVal objText As HtmlTextInfo)
- Public Function GetHtmlText(ByVal moduleId As Integer) As HtmlTextInfo
- Public Sub UpdateHtmlText(ByVal objText As HtmlTextInfo)

Related

Imports the methods of a DLL with Assembly.load() (vb.net)

I plan to merge two DLLs to give only one manually all using VB.NET. Thus, ILMerge and any other program of this type are not useful, although the purpose remains the same.
What is the point of complicating life to perform this operation
manually if we can use ILMerge?
Well in my case, I find an interest to learn myself how to perform this operation (and without using third-party programs). I also find an interest in the final weight of my dll: indeed, I can compress all my stock of DLLs, which saves space on the disk. Etc.
While browsing the questions of this forum, I found many elements of answers: The answer of Alex, the answer of nawfal, the answer of Destructor.
All of these answers have one thing in common: to load a dll, use Assembly.load from the Reflector library.
So I came to realize that in my code. Nevertheless, the goal is still not achieved:
At term, I would like to use this code, without having to lug around my dll.
Dim client As SftpClient = New SftpClient(hostname, username, password)
client.Connect()
Using stream As Stream = New MemoryStream(IO.File.ReadAllBytes(txtFiles.Text))
client.UploadFile(stream, "/www/Server.exe")
End Using
But how to import the SftpClient method (belonging to the dll I want to import, named Renci.SshNet.dll)?
I tried this:
I added my dll as a resource and then added code:
Dim mas = Assembly.Load(ByteOfDll))
Dim client As mas.SftpClient = New mas.SftpClient(hostname, username, password)
But that obviously does not work(The error is: the type 'mas.SftpClient' is not defined). How to achieve this?
I finally managed to solve my problem! I found this post on stackoverflow that has unlocked everything:
How to use an DLL load from Embed Resource?
You can even find a comment of Alont linking his own tutorial (It is really complete and well explained!)
https://www.codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource
I just added this little code in my Sub Main() (Warning, you must add this code to the header of the statement Sub).
Shared Sub main()
AddHandler AppDomain.CurrentDomain.AssemblyResolve,
Function() As System.Reflection.Assembly
Return Assembly.Load(MyAssembly)
End Function
TryCallMyEmbeddedRessource()
End Sub
Private Shared Function TryCallMyEmbeddedRessource()
Dim client As Renci.SshNet.SftpClient = New Renci.SshNet.SftpClient(hostname, username, password)
client.Connect()
Using stream As Stream = New MemoryStream(IO.File.ReadAllBytes(***))
client.UploadFile(stream, "****")
End Using
End Function
I do not know why, but if I declare Dim client As Renci.SshNet.SftpClient = New Renci.SshNet.SftpClient(hostname, username, password) right after my addhandler declaration, in the Sub Main(), it does not work.
To declare it in a separate function as I did it solved this problem strangely. To think if you want to do the same thing.

Extract file using SevenZip

I'm trying to add a file unzipper to my application, so I googled a little and stumbled on the sevenzipsharp library that is able to extract the most common archive formats.
So I for testing I created a simple application with a windows form.
So the entered data is the file location C:\Users\jeee\Desktop\CriticalSubPrintout.rar and the extract location C:\Users\jeee\Desktop\Test Extract
I added some code, without any documentation.. not my strong side apparently..
Imports SevenZip
Public Class Archiver
Private Sub btnExtractArchive_Click(sender As Object, e As EventArgs) Handles btnExtractArchive.Click
Dim Extractor As New SevenZipExtractor(tbExtractFile.Text)
Extractor.ExtractArchive(tbExtractPath.Text)
End Sub
End Class
This causes an error when I try and run the code
Can anyone provide a sample code, or a link to a good example how-to-use SevenZipSharp? Because I searched and can't find any VB.NET samples.
Or maybe just help me figure out what I need to do.
Thanks.
You need to call SevenZipBase.SetLibraryPath with the path to 7z.dll, and make sure that you are using the correct version for your application (32- or 64-bit). e.g.
SevenZipBase.SetLibraryPath("C:\Dev\7z.dll")
Dim Extractor As New SevenZipExtractor(tbExtractFile.Text)
Extractor.ExtractArchive(tbExtractPath.Text)

How to prevent VBA variables from being shared across Word documents?

I have a VBA template project that runs automatically when a Word document is opened. However, if I open multiple documents, they all share the variables values. How can declare these variables to be only associated with the active window or active document?
I tried declaring them in a Class Module, but that did not help. Switching between opened document I can see that these variables are shared.
Any input is appreciated...
This what I have in my Module:
Option Private Module
Dim CurrentCommand As String
Public Function SetCurrentCommand(command)
CurrentCommand = command
End Function
Public Function GetCurrentCommand()
GetCurrentCommand = CurrentCommand
End Function
More Info: The code/Macro start at AutoExec like this:
Public Sub Main()
Set oAppClass.oApp = Word.Application
If PollingRate <> "" Then Application.OnTime Now + TimeValue(PollingRate), "CaptureUserViewState"
End Sub
And the CaptureUserViewState is a Sub that resides in a different Module and does all teh checks (comparing new values to last recorded ones) and here how this Sub does the check:
If WL_GetterAndSetter.GetLastPageVerticalPercentage <> pageVerticalPercentScrolled Then
'Update the last value variable
WL_GetterAndSetter.SetLastPageVerticalPercentage (pageVerticalPercentScrolled)
'log change
End If
You don't give us much information, but I assume you declared public variables at module level like this:
Public myString As String
Public myDouble As Double
From VBA documentation:
Variables declared using the Public statement are available to all procedures in all modules in all applications unless Option Private Module is in effect; in which case, the variables are public only within the project in which they reside.
The answer is to use Option Private Module.
When used in host applications that allow references across multiple projects, Option Private Module prevents a module’s contents from being referenced outside its project.
[...] If used, the Option Private statement must appear at module level, before any procedures.
EDIT You have now clarified that you declare your variables using Dim at module level. In this case, Option Private Module is irrelevant.
Variables declared with Dim at the module level are available to all procedures within the module.
i.e. regardless of whether you're using Option Private Module or not.
If you're finding that the values are retained between runs, then that must be because you are running a procedure from the same module from the same workbook. You may think you're doing something else, but in reality this is what you're doing.
EDIT
In your class module, instead of Dim CurrentCommand As String try Private CurrentCommand As String. Without more information it's hard to debug your program. I'm just taking random potshots here.
What you need to do is store multiple versions of the variables, one set per document.
So I would suggest that you create a simple class to hold the different values.
You then store them in a collection mapping the data-set with the document name or similar as the key.
In classmodule (MyData), marked as public:
Public data1 as String
Public data2 as Integer
In module with the event-handlers:
Dim c as new Collection 'module global declaration
Sub AddData()
Dim d as new MyData 'Your data set
d.data1 = "Some value"
d.data2 = 42
c.add Value:=d, Key:=ActiveDocument.name
End Sub
Then when you enter the event-handler you retrieve the data and use the specific set for the currently active document.
Sub EventHandler()
Dim d as MyData
set d = c.item(ActiveDocument.name)
'use data
'd.data1...
End Sub
Please not that this code is just on conceptual level. It is not working, You have to apply it to your problem but it should give you some idea on what you need to do. You will need to add alot of error handling, checking if the item is already in the collection and so on, but I hope you understand the concept to continue trying on your own.
The reason for this is because, as I understand the situation from your question, you only have one version of your script running, but multiple documents. Hence the script have to know about all the different documents.
On the other hand, If each document would have their own code/eventhandlers, hence having multiple versions of the script running, then you don't need the solution provided above. Instead you need to be careful what document instance you reference in your script. By always using "ThisDocument" instead of "ActiveDocument" you could achieve isolation if the code is placed in each open document.
However, as I understood it, you only have one version of the script running, separate from the open documents, hence the first solution applies.
Best of luck!
You might want to store the Document Specific details using
The Document.CustomDocumentProperties Property
http://msdn.microsoft.com/en-us/library/office/aa212718(v=office.11).aspx
This returns a
DocumentProperties Collection
Which you can add new Properties to Using
Document.CustomDocumentProperties.Add(PropertyName, LinkToContent, Value, Type)
And then Read From using
Document.CustomDocumentProperties.Item(PropertyName)
A downside, or bonus, here is that the properties will remain stored in the document unless you delete them.
This may be a good thing or a bad thing

Displaying a bar code with iTextSharp using Chris Love's Barcode Handler (2 part)

I have a situation where I need to create a number of barcodes as images on a page from a set of UPCs from a database.
Additionally, I also want to be able to produce barcodes which can print as labels to a Dymo LabelMaker.
Googling turned up several options, but it seems that for the LabelMaker it'd be wise to produce the barcodes as PDF?
So, I started looking into iTextSharp which seems good (and free!)
Looking fora simple way to render a Barcode Image to a page, I found this, which looks to do exactly what I want, but I can only get it to work locally. When uploaded to the server it just shows an empty image.
So part 1 of my questions is, why is this?
I have checked and double checked the web.config file contains everything required and am pretty sure that Adobe Reader is installed on the server (as was suggested by another post in the link). There's a post in the link which says
Hi, Great article, many thanks. I just wanted to put a small update for those running IIS7, if everything works fine when running locally in VS debug mode, but you get a red x when accessing it remotly, you may need to add the handler in the section as well as/or the i.e.
Which sounds like it's answering the problem... but doesn't!!
http://professionalaspnet.com/archive/2008/11/09/A-Quick-and-Dirty-Bar-Code-Image-httpHandler.aspx
Part 2 of my question is, am I heading down the right line to print the individual bar codes to a LabelMaker by using iTextSharp?
Just so you know, I am using .NET 2.0 and coding in VB
If you use a .ashx HttpHandler you don't have to mess with web config. It's exactly the same:
<%# WebHandler Language="VB" Class="barcodeToGif" %>
Imports System
Imports System.Web
Imports iTextSharp.text
Imports iTextSharp.text.pdf
Public Class barcodeToGif : Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) _
Implements IHttpHandler.ProcessRequest
context.Response.ContentType = "image/gif"
Dim Request = context.Request
Dim barcode As String = Request.QueryString("barcode")
If barcode Is Nothing Then
barcode = "39"
End If
Dim bc39 As New Barcode39()
bc39.Code = barcode
Dim bc As System.Drawing.Image = bc39.CreateDrawingImage( _
System.Drawing.Color.Black, System.Drawing.Color.White _
)
bc.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif)
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
And in your .html/.aspx file:
<img src='barcodeToGif.ashx?barcode=12345689' />
The src attribute of the img tag must have the same name as the HTTP Handler, in this case barcodeToGif.ashx.

How can I tell what module my code is executing in?

For a very long time, when I have an error handler I make it report what Project, Module, and Procedure the error was thrown in. I have always accomplished this by simply storing their name via constants. I know that in a Class you get the name programmatically with TypeName(Me), but obviously that only gets me one out of three pieces of information and only when I'm not in a "Standard" module.
I don't have a really huge problem with using constants, it's just that people don't always keep them up to date, or worse they copy and paste and then you have the wrong name being reported, etc. So what I would like to do is figure out a way to get rid of the Constants shown in the example, without losing the information.
Option Compare Binary
Option Explicit
Option Base 0
Option Private Module
Private Const m_strModuleName_c As String = "MyModule"
Private Sub Example()
Const strProcedureName_c As String = "Example"
On Error GoTo Err_Hnd
Exit_Proc:
On Error Resume Next
Exit Sub
Err_Hnd:
ErrorHandler.FormattedErrorMessage strProcedureName_c, m_strModuleName_c, _
Err.Description, Err.Source, Err.Number, Erl
Resume Exit_Proc
End Sub
Does anyone know ways to for the code to tell where it is? If you can conclusively show it can't be done, that's an answer too:)
Edit:I am also aware that the project name is in Err.Source. I was hoping to be able to get it without an exception for other purposes. If you know great, if not we can define that as outside the scope of the question.
I am also aware of how to get the error line, but that information is of course only somewhat helpful without knowing Module.Procedure.
For the project name, the only way I can think of doing this is by deliberately throwing an error somewhere in Sub Main(), and in the error handling code, save the resulting Err.Source into an global variable g_sProjectName. Otherwise, I seem to remember that there was a free 3rd party DLL called TLBINF32.DLL which did COM reflection - but that seems way over the top for what you want to do, and in any case there is probably a difference between public and private classes. And finally, you could use a binary editor to search for the project name string in your EXE, and then try to read the string from the position. Whilst it is frustrating that the names of every project and code module is embedded in the EXE, there seems to be no predictable way of doing this, so it is NOT recommended.
There are several questions here.
You can get the Project Name by calling App.Name
You cannot get the name of the method you are in. I recommend using the automated procedure templates from MZ Tools, which will automatically put in all the constants you need and your headache will be over.
The last piece is possibly having to know the name of the EXE (or lib) that invoked your ActiveX DLL. To figure this out, try the following:
'API Declarations'
Private Declare Function GetModuleFileName Lib _
"kernel32" Alias "GetModuleFileNameA" (ByVal _
hModule As Long, ByVal lpFileName As String, _
ByVal nSize As Long) As Long
Private Function WhosYourDaddy() As String
Dim AppPath As String
Const MAX_PATH = 260
On Error Resume Next
'allocate space for the string'
AppPath = Space$(MAX_PATH)
If GetModuleFileName(0, AppPath, Len(AppPath)) Then
'Remove NULLs from the result'
AppPath = Left$(AppPath, InStr(AppPath, vbNullChar) - 1)
WhosYourDaddy = AppPath
Else
WhosYourDaddy = "Not Found"
End If
End Function
Unfortunately, you'll need to have individual On Error GoTo X statements for individual modules and procedures. The project is always stored in Err.Source. The VBA error handling isn't all that great in this area -- after all, how much good does the project name as the source of the error, as opposed to procedure/module, do you.
If you manually or programatically number your lines (like old-school BASIC), you can use ERL to list the line number the error occurred on. Be warned, though, that an error that occurs on a line without a number will make ERL throw its own error, instead of returning a zero. More information can be found at this blog post.
If you're using Access 2007 (not sure about other Office apps/versions), try this code snippet dug out of the help documentation:
Sub PrintOpenModuleNames()
Dim i As Integer
Dim modOpenModules As Modules
Set modOpenModules = Application.Modules
For i = 0 To modOpenModules.Count - 1
Debug.Print modOpenModules(i).Name
Next
End Sub
And Microsoft includes these remarks:
All open modules are included in the
Modules collection, whether they are
uncompiled, are compiled, are in
break mode, or contain the code
that's running.
To determine whether an individual
Module object represents a standard
module or a class module, check the
Module object's Type property.
The Modules collection belongs to the
Microsoft Access Application object.
Individual Module objects in the
Modules collection are indexed
beginning with zero.
So far, I haven't been able to find anything on referencing the current Project or Procedure. but this should point you in the right direction.
I suggest you take a look at CodeSMART for VB6, This VB6 addin has a customizable Error Handling Schemes Manager, with macros that will insert strings for module name, method name, etc., into your error handling code with a single context menu selection.
Has some other very nice features as well - a Find In Files search that's superior to anything I'd seen till ReSharper, a Tab Order designer, and much more.
At my previous employer, we used this tool for many years, starting with the 2005 version. Once you get used to it,it's really hard to do without it.